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'];
}
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 3 table : events,students and parent_student_relation.
events
id | class_id | title
----------------------
1 | 16 | ABC
2 | 17 | JKL
3 | 18 | XYZ
students
id | class_id | name
----------------------
5 | 18 | StudentName1
6 | 17 | StudentName2
7 | 16 | StudentName3
parent_student_relation
student_id | parent_id
----------------------
4 | 10
5 | 10
6 | 11
7 | 11
Now i want to get data from events where i pass parent_id = 10 then get following output.
Output
id | class_id | title
----------------------
3 | 18 | XYZ
And i pass parent_id = 11 then get following output.
Output
id | class_id | title
----------------------
1 | 16 | ABC
2 | 17 | JKL
I tried with following code :
$q_student = "SELECT student_id FROM parent_student_relation WHERE parent_id = " . $parent_id;
$q_class = "SELECT class_id FROM students WHERE id IN($q_student) GROUP BY class_id";
$q = "SELECT * FROM events WHERE class_id IN($q_class)";
So i can get perfect output in $query = mysql_query($q);
But I want to all in only one join query. So how can do it?? Or its possible or not?
try this
$query="SELECT *
FROM parent_student_relation AS a
JOIN students AS b
ON a.student_id = b.id
JOIN events AS c
ON b.class_id = c.class_id
WHERE a.parent_id = " . $parent_id;
Use this:
$query="select e.id,e.class_id,e.title,s.id from event e
inner join student s on e.class_id=s.class_id
inner join parent_student_relation p on s.id=p.student_id
where p.parent_id=$parent_id";
I have 2 tables:
sma_db
+----+----------+-------+
| ID | title | catid |
+----+----------+-------+
| 1 | Hi | 4 |
| 2 | Hello | 4 |
| 3 | Test | 5 |
+----+----------+-------+
sma_files
+----+----------+---------+
| ID | name |entry_id |
+----+----------+---------+
| 1 | a.jpg | 1 |
| 2 | b.jpg | 1 |
| 3 | c.jpg | 2 |
+----+----------+---------+
My query as:
$sql = mysql_query("SELECT * FROM sma_db
LEFT OUTER JOIN sma_files
ON sma_db.id = sma_files.entry_id
WHERE catid = '4'") or die(mysql_error());;
while($affcom = mysql_fetch_assoc($sql)){
$title = $affcom['title'];
$name = $affcom['name'];
echo $title;
echo $name;
}
How to select only one row from sma_files table ???
The output for above query:
Hi a.jpg
Hi b.jpg
Hello c.jpg
The output I need:
Hi a.jpg
Hello c.jpg
$sql = mysql_query("SELECT * FROM sma_db
LEFT OUTER JOIN sma_files
ON sma_db.id = sma_files.entry_id
WHERE catid = '4'
GROUP BY sma_files.entry_id")
or die(mysql_error());
try below query
SELECT * FROM `sma_db`
INNER JOIN `sma_files`
ON `sma_db`.`id` = `sma_files`.`entry_id`
WHERE `sma_db`.`catid` = '4'"
Use Group By
SELECT * FROM sma_db
LEFT OUTER JOIN sma_files
ON sma_db.id = sma_files.entry_id
WHERE catid = '4'
GROUP BY `entry_id`
There is two tables there is nor relation between both tables,
structure: table_one
+---------+--------+-----------+
| name | age |insertTEMP |
+---------+--------+-----------+
| cat | 12 |02-02-2014 |
| dog | 13 |03-04-2014 |
+---------+--------+-----------+
structure: table_two
+---------+--------+---------------+
| book | pages | insertTEMP |
+---------+--------+---------------+
| book1 | 34 | 05-02-2014 |
| book2 | 54 | 04-03-2014 |
+---------+--------+---------------+
now the idea is here i want to list records from both table so i keep bellow function to list them.
public function recentALL() {
$sql = "select * from table_one, table_two ORDER BY insertTEMP";
$q = $this -> conn -> prepare($sql);
$q -> execute();
return $row = $q -> fetchAll();
}
and i fetch it in the view,
$data2 = $functions->recentAll();
foreach ($data2 as $data3){
echo $data3['name'] . $data3['book'] . '<br />';
}
how i can make it to show like:
+---------+--------+
| cat | NULL |
| null | book1 |
| null | book2 |
| dog | null |
+---------+--------+
this based on the insertTEMP
Use the following query
Select * from (
Select name as Name, null as Book,insertTEMP from table_one
UNION ALL
select null as Name, book as Book,insertTEMP from table_two
) as tmp
Order by tmp.insertTEMP asc
Change the column names in your code as per query
I have this scenario.
I input $groupid="1";
main table
----------------------
| groupid | postid |
|---------------------|
| 1 | 1 |
| 2 | 2 |
| 1 | 3 |
$query = "SELECT postid FROM `mainl` WHERE groupid='$groupid'";
$result = mysql_query($query);
// a group of postids belonging to that groupid which should hold [1, 3] for groupid=1
while($row = mysql_fetch_array($result)) {
$postids[] = $row["postid"];
}
second table
-------------------------------------------
| postid | commentid | comment |
-------------------------------------------
| 1 | 1 | testing 1 |
| 1 | 2 | testing 2 |
| 1 | 3 | what? |
| 2 | 1 | hello |
| 2 | 2 | hello world |
| 3 | 1 | test 3 |
| 3 | 2 | begin |
| 3 | 3 | why? |
| 3 | 4 | shows |
$query = "SELECT * FROM `second`";
$result = mysql_query($query);
while ($row = mysql_fetch_array($result)) {
if (in_array($row["postid"], $postids)) {
$comments[$row["postid"]] = $row["comment"];
But how should I take care of commented
I want the postid array to be [1,3] and my comment array to be
[commentid: comment] [1:testing1, 2: testing2, 3: what?] for postid=1
and
[1:test3, 2:begin, 3: why? 4:shows] for postid=3
how should be arrange everything such comment are associated with commentid and postid?
First I would follow rokdd suggestion and make 1 query
SELECT m.groupid , s.postid, s.commentid, s.comment FROM `main1` m JOIN `second` s USING (postid) where m.groupid = 1
Then I would make a multi-dimensional array
while ($row = mysql_fetch_array($result))
$groups[$row['groupid'][$row['postid']][$row['commentid']=$row['comment'];
then to iterate through the array
foreach($groups as $group)
foreach($group as $post)
foreach($post as $comment)
echo $comment;
This will keep track of groups also (if you ever want to select by more than 1 group.
If you don't care about groups just drop off the first part of the array.
while ($row = mysql_fetch_array($result))
$posts[$row['postid']][$row['commentid']=$row['comment'];
foreach($posts as $post)
foreach($post as $comment)
echo $comment;
I guess to use the join in sql so that you will have one statement:
SELECT * FROM second as second_tab LEFT join main as main_table ON main_table.post_id=second_table.post_id WHERE main_table.group_id="3"
Well not tested now but thats a way to solve some of your problems!