I have table like this
user
id | name
1 | john
2 | alicia
3 | alex
follow_table
id | follow | follower
1 | john | alex
2 | alicia | alex
posts
id | title | content | name
1 | title john | ....... | john
2 | title alicia | ....... | alicia
3 | title alex | ....... | alex
Example ;
$id = 'alex';
$select_one = select * from follow_table where follower = '$id';
$query_one = mysqli_query($mysqli, $select_one) or die (mysqli_error($mysqli));
while ($follow = mysqli_fetch_array($query_one)) {
$follow = $follow['follow'];
$select_two = select * from posts where name = '$follow';
$query_two = mysqli_query($mysqli, $select_two) or die (mysqli_error($mysqli));
while ($posts = mysqli_fetch_array($query_two)) {
echo $posts['title'];
}
}
results will like this:
id | title
1 | title john
2 | title alicia
actual sql above is correct, but I just wanted to add a query in the $follow.
my question is, how to get user.id 3 (alex) into the field $follow?
I want something like this
id | title
1 | title john
2 | title alicia
3 | title alex
thank you for that already willing to help
Replace $select_one by :
SELECT name
FROM user
JOIN follow_table ON (
follow_table.follower = user.name
OR follow_table.follow = user.name
)
WHERE follower = '$id';
This will retrieve every user followed by alex, and alex himself.
You can use CONCAT() or CONCAT_WS() as a derived field to concatenate the results of two columns.
SELECT
CONCAT_WS(' ', title, name) as full_name
FROM
//...
You have to use alias in this case also you have to implement your select query, I have tried this and works well,
<?php
$select_one = select * from follow_table where id = '$id';
$query_one = mysqli_query($mysqli, $select_one) or die (mysqli_error($mysqli));
while ($follow = mysqli_fetch_array($query_one)) {
$follow = $follow['follow'];
$select_two = select posts.name as posted_name,posts.* from posts where name = '$follow';
$query_two = mysqli_query($mysqli, $select_two) or die (mysqli_error($mysqli));
while ($posts = mysqli_fetch_array($query_two)) {
echo $posts['title'];
echo $posts['posted_name'];
}
}
Related
Column title has a lot of duplicated values, more than once.
I need to update the column so, for example if 'gold' is duplicated - it becomes 'gold 1', 'gold 2', etc.
Something like this:
$st = $db->query("select id, title from arts order by title asc");
$st->execute();
$x = 0;
while($row = $st->fetch()){
$title = $row['title'];
//if($title.is duplicated){
$x++;
$title .= ' ' . $x;
$stb = $db->query("update arts set title = '" . $title . "' where id = " . $row['id']);
$stb->execute();
}
}
Any help?
It would be more efficient to do this in pure SQL rather than using PHP. Here is an approach that uses window functions, available in MySQL 8.0.
You can use a subquery to count how many title duplicates exists for each record, and assign a rank to each record within groups of records having the same title. Then, you can JOIN the subquery with the table to update. Where more than one record exists, you can append the row number to every record in the group.
Query:
UPDATE arts a
INNER JOIN (
SELECT
id,
title,
COUNT(*) OVER(PARTITION BY title) cnt,
ROW_NUMBER() OVER(PARTITION BY title ORDER BY id) rn
FROM arts
) b ON a.id = b.id
SET a.title = CONCAT(a.title, b.rn)
WHERE cnt > 1;
Demo on DB Fiddle
Sample data:
| id | title |
| --- | ------ |
| 10 | silver |
| 20 | gold |
| 30 | gold |
| 40 | bronze |
| 50 | gold |
| 60 | bronze |
Results after running the update query:
| id | title |
| --- | ------- |
| 10 | silver |
| 20 | gold1 |
| 30 | gold2 |
| 40 | bronze1 |
| 50 | gold3 |
| 60 | bronze2 |
Please see below code that working for me
// Create connection
$conn = new mysqli($servername, $username, $password,$dbname);
// get all row
$sql = "select id, title from arts order by title asc";
$result = $conn->query($sql);
while ($row=$result->fetch_assoc()) {
$title=$row['title'];
// select where title is same
$sql = "select * from arts where title='".$title."'";
$result2 = $conn->query($sql);
// if number of row is greater then one
if ($result2->num_rows > 1){
$x=0;
while ($row2=$result2->fetch_assoc()) {
$id=$row2['id'];
// skip first row
if($x>0){
$newTitle=$title.' '.$x;
$uquery = "update arts set title='".$newTitle."' where title='".$title."' and id=$id";
$update = $conn->query($uquery);
}
$x++;
}
}
}
and after query run
This works in MySql 5.7:
update arts a inner join (
select * from (
select t.id,
(
select count(*) + 1 from arts
where id < t.id and title = t.title
) counter
from arts t
) t
) t on t.id = a.id
set a.title = concat(a.title, ' ', t.counter)
where a.title in (
select h.title from (
select title from arts
group by title
having count(*) > 1
) h
);
See the demo.
For data:
| id | title |
| --- | -------- |
| 1 | silver |
| 2 | gold |
| 3 | diamond |
| 4 | bronze |
| 5 | gold |
| 6 | bronze |
| 7 | gold |
the result is
| id | title |
| --- | -------- |
| 1 | silver |
| 2 | gold 1 |
| 3 | diamond |
| 4 | bronze 1 |
| 5 | gold 2 |
| 6 | bronze 2 |
| 7 | gold 3 |
I think It would be more efficient to do this in SQL too, but you may can do a function to validate the duplicate, something like this:
function isDuplicated( $title, $db ){
$dp = $db->query("SELECT * FROM arts WHERE title = $title");
if ( $dp->num_rows > 1)
return true;
return false;
}
$st = $db->query("select id, title from arts order by title asc");
$st->execute();
$x = 0;
while($row = $st->fetch()){
$title = $row['title'];
if( isDuplicated( $title, $db ) ){
$x++;
$title .= ' ' . $x;
$stb = $db->query("update arts set title = '" . $title . "' where id = " . $row['id']);
$stb->execute();
}
}
I have the following 2 tables.
| ID | Name | Category |
|----|-------------|----------|
| 1 | Foo bar | 3 |
| 2 | Bar foo | 2 |
| 3 | Baz Foo | 3 |
| 4 | Baz Foo2 | 1 |
| 5 | Baz Foo3 | 1 |
| 3 | Baz Foo | 1 |
| ID | Category_name |
|----|---------------|
| 1 | Cat 111 |
| 2 | Cat 222 |
| 3 | Cat 3333 |
I want to display all categories with counter, example:
Cat111 - 3
Cat222 - 2
Cat333 - 2
I tried to do it by the following way, but its not working:
$query = mysqli_query('SELECT * FROM gallery');
while($row = mysqli_fetch_assoc($query)) {
$query_cat = mysqli_query($conn, "SELECT * FROM `pics_cat` WHERE id = '".$row['category']."' GROUP BY category_name");
$rowCat = mysqli_fetch_assoc($query_cat);
echo $rowCat['category_name'];
echo $rowCat['cnt'];
}
You are not sharing the names of the tables, but I assume the first one is Gallery and the second one is pics_cat
If your tables are not going to be very large, I suggest you to solve everything with a single join query, which simplifies the logic of your script.
$query = mysqli_query($conn, 'SELECT p.Category_name,COUNT(g.ID) AS cnt FROM `gallery` AS g LEFT JOIN `pics_cat` AS p ON p.ID = g.Category GROUP BY p.ID');
while($row = mysqli_fetch_assoc($query)) {
echo $rowCat['Category_name'];
echo $rowCat['cnt'];
}
If you prefer to do this with 2 queries in a loop, it's much easier to start from the Category table and then move to the gallery
$query = mysqli_query($conn, 'SELECT * FROM `pics_cat` ORDER BY ID');
while($row = mysqli_fetch_assoc($query)) {
$query_count = mysqli_query('SELECT COUNT(ID) AS cnt FROM `gallery` WHERE Category = '.$row['ID'].'');
$row_count = mysqli_fetch_assoc($query_count);
echo $row['Category_name'];
echo $row_count['cnt'];
}
I have a table named users with a column called user_subs. It looks like this.
In user_subs I have stored the specific users session username. Lets say this specific users name is James.
Now how would I loop through a specific user_subs looking for "James" and remove him from that specific user_subs without removing all the other names.
This is what I have so far and the only problem is, its deleting all the usernames in user_subs instead of just "James".
if(isset($_GET['p_id'])) {
$the_post_id = $_GET['p_id'];
$the_post_author = $_GET['author'];
}
if(isset($_POST['delete_sub'])) {
$username = $_SESSION['username'];
$query = "SELECT user_subs FROM users WHERE username = '{$username}' ";
$select_users_by_id = mysqli_query($connection, $query);
while ($row = mysqli_fetch_array($select_users_by_id)) {
$user_subs = explode(',', $row['user_subs']);
foreach($user_subs as $out) {
$query = "UPDATE users SET user_subs = null WHERE username = '{$the_post_author}' ";
$unsubscribe_user = mysqli_query($connection, $query);
echo "Unsubscribed";
}
}
}
THIS IS JUST IN TEST, PREPARED STATEMENTS WILL BE USED BEFORE GOING LIVE
Thank you for your time.
I second the other user's comment about moving this column to a different table. In the meanwhile, if you want to achieve what you are asking for, you can try removing the user name from the column value and update it with the remaining text.
if(isset($_POST['delete_sub'])) {
$username = $_SESSION['username'];
$query = "SELECT user_subs FROM users WHERE username = '{$username}' ";
$select_users_by_id = mysqli_query($connection, $query);
while ($row = mysqli_fetch_array($select_users_by_id)) {
$user_subs = str_replace($username . ',', '', $row['user_subs']);
$query = "UPDATE users SET user_subs = '{$user_subs}' WHERE username = '{$the_post_author}' ";
$unsubscribe_user = mysqli_query($connection, $query);
echo "Unsubscribed";
}
}
OPTION-2
$user_subs = explode(',', $row['user_subs']);
$user_subs_new = [];
foreach($user_subs as $out) {
if ($out !== $username) {
$user_subs_new[] = $out;
}
}
$user_subs = implode(',',user_subs_new);
$query = "UPDATE users SET user_subs = '{$user_subs}' WHERE username = '{$username}' ";
$unsubscribe_user = mysqli_query($connection, $query);
echo "Unsubscribed";
}
Let's start over. Let's start here, in fact...
DROP TABLE IF EXISTS users;
CREATE TABLE users
(user_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,email VARCHAR(20) NOT NULL UNIQUE
);
DROP TABLE IF EXISTS user_subs;
CREATE TABLE user_subs
(user_id INT NOT NULL
, sub_id INT NOT NULL
, active TINYINT NOT NULL DEFAULT 1
, PRIMARY KEY(user_id,sub_id)
);
INSERT INTO users VALUES
(1,'b.smyth634#gmail.com'),
(2,'james#gmail.com'),
(3,'f#gmail.com'),
(4,'sally#gmail.com'),
(5,'thomas#gmail.com');
INSERT INTO user_subs (user_id,sub_id) VALUES
(1,5),
(1,2),
(1,1),
(1,4),
(2,1),
(2,2),
(2,4);
SELECT * FROM users;
+---------+----------------------+
| user_id | email |
+---------+----------------------+
| 1 | b.smyth634#gmail.com |
| 2 | james#gmail.com |
| 3 | f#gmail.com |
| 4 | sally#gmail.com |
| 5 | thomas#gmail.com |
+---------+----------------------+
SELECT * FROM user_subs;
+---------+--------+--------+
| user_id | sub_id | active |
+---------+--------+--------+
| 1 | 5 | 1 |
| 1 | 2 | 1 |
| 1 | 1 | 1 |
| 1 | 4 | 1 |
| 2 | 1 | 1 |
| 2 | 2 | 1 |
| 2 | 4 | 1 |
+---------+--------+--------+
SELECT u.*
, GROUP_CONCAT(us.sub_id) subs
FROM users u
JOIN user_subs us
ON us.user_id = u.user_id
GROUP
BY u.user_id;
+---------+----------------------+---------+
| user_id | email | subs |
+---------+----------------------+---------+
| 1 | b.smyth634#gmail.com | 1,2,4,5 |
| 2 | james#gmail.com | 1,2,4 |
+---------+----------------------+---------+
From here we have a choice. We can either DELETE subs we no longer wish to consider, or simply UPDATE them as 'inactive'.
Either way, we just need a DELETE or an UPDATE. So no SELECT needed. In fact a SELECT would, as I mentioned, be counterproductive - because a user may modify the data set in between the execution of the SELECT and the execution of the UPDATE/DELETE. This is known as a 'race condition'.
I have a page that dynamically looks for comments and replies in a databes and produce code accordingly. Now, i want to count the number of replies per comment (comment_id in the table below) and if they are more than 3 show "There are XX replies" else show all the replies.
The table of replies looks like this
+---------------------+----+---------+------------------+------------+
| date | id | user_id | reply | comment_id |
+---------------------+----+---------+------------------+------------+
| xxxx-xx-xx xx:xx:xx | 1 | 01 | adasdasdasdasdas | 8 |
| xxxx-xx-xx xx:xx:xx | 2 | 02 | test | 8 |
| xxxx-xx-xx xx:xx:xx | 3 | 03 | m no | 8 |
| xxxx-xx-xx xx:xx:xx | 4 | 03 | mno | 8 |
| xxxx-xx-xx xx:xx:xx | 5 | 05 | hehe | 10 |
+---------------------+----+---------+------------------+------------+
id is the id of the reply
user_id is the user who wrote the comment
comment_id is the id of the father'reply (a.k.a. the comment)
What i've tried so far is:
$querys = "SELECT * FROM replies
WHERE comment_id = {$writeComment['comment_id']}
ORDER BY date DESC;";
$findReplies = mysqli_query($_SESSION['connection'], $querys);
while ($reply = mysqli_fetch_assoc($findReplies)) {
$countReplies = "SELECT * FROM replies
GROUP BY comment_id
HAVING COUNT( DISTINCT comment_id ) > 3;";
$moreThanThree = mysqli_query($_SESSION['connection'], $countReplies);
if(!$moreThanThree){
// code for lass than 3 replies
} else {
// there are xx replies
// show all replies
}
You can use a group by query to find the count of replies. Then using these results you can display the text accordingly.
SELECT comment_id, count(*) FROM replies GROUP BY comment_id
you can use this query:
select reply, (select count(*) from replies replies_inner where replies_inner.comment_id = replies.comment_id) as reply_count from replies
then you can loop through php:
$previuos_comment=$rows[0]['comment_id'];
foreach($rows as $row) {
$reply_count =$row['reply_count '];
if($reply_count>3) {
echo 'xxxxxx';
} else {
if($previuos_comment==$row['comment_id']) {
echo $row['reply'];
}
$previuos_comment=$row['comment_id'];
}
}
So i managed to solve the problem, partially thank to #Gouda Elalfy:
while ($reply = mysqli_fetch_assoc($findReplies)) {
$querya = "SELECT comment_id, (SELECT COUNT(*) FROM replies
WHERE comment_id = {$writeComment['comment_id']})
AS reply_count FROM replies";
$findHowMany = mysqli_query($_SESSION['connection'], $querya);
$moreThanThree = mysqli_fetch_assoc($findHowMany);
if($moreThanThree['reply_count'] < 3){
//print comment
} elseif (isset($prevId)){
if(prevID != $reply['id']){
// print "there are xx comments"
break;
}
}
$prevId = $reply['id'];
}
I can't create an appropriate query which could select all comments connected with one particular image and get those comments authors.
I would like to create a query something like:
select a comment where comment_id == image_id && user_id(table comments) == user_id(table users)
This is MySQL part:
Table 'comments'
id | comment | user_id | image_id |
1 | test 1 | 1 | 1 |
2 | test 2 | 1 | 2 |
3 | test 3 | 2 | 1 |
Table 'users'
id | name |
1 | test1 |
2 | test2 |
Table 'images'
id | img |
1 | test.jpg |
2 | test.jpg |
3 | test.jpg |
4 | test.jpg |
Controller Part:
$imageId = $filter->filter ($request->getParam('id'));
$this->view->imageId = $filter->filter ($request->getParam('id'));
$this->view->imageChosen = $images->fetchRow($images->select()->where('id = ?', $imageId));
$users = new Users();
$userChosen = new Users();
$comments = new Comments();
$this->view->comments = $comments->fetchAll();
$this->view->userChosen = $users->fetchRow($users->select()->where('id = ?', $this->view->imageChosen->author_id));
$this->view->commentsChosen = $comments->fetchAll($comments->select()->where('id = ?', $imageId));
View part:
for ($i=0; $i < count($this->commentsChosen); $i++) {
echo $this->commentChosen[$i]->comment;
}
Right now I only get the very first comment.
What I mean is I need all comments belonging to each picture as well as authors info.
Thanks for your help!
As you've said, you can fetch the image info with your query, I'll extend it in order to fetch the user info too:
$select = $comments->select()->setIntegrityCheck(false)
->from('comments')
->joinInner('users', 'users.id = comments.user_id')
->where('comments.image_id = ?', $this->view->imageChosen->id);
$this->view->commentsChosen = $comments->fetchAll($select);
The generated query would be:
SELECT comments.* users.* FROM comments
INNER JOIN users ON users.id = comments.user_id
WHERE comments.image_id = [Your_id_here]
I hope this helps!
I've managed to get all comments belonging to each picture.
Controller:
$this->view->commentsChosen = $comments->fetchAll($comments->select()->where('image_id = ?', $this->view->imageChosen->id));
View:
for ($i=0; $i<count($this->commentsChosen); $i++) {
echo $this->commentsChosen[$i]->comment;
//Have 'user_id' only
echo $this->commentsChosen[$i]->user_id;
}
However, I still can't get authors details.