SQL display and fetch GROUP BY categories - php

I have a list of authors and I would like to display it by book genre, like this:
Horror
Stephen King
Author 2
Author 3
...
Comedy
Author 4
Author 5
...
In my database I have an author table:
t_author
aut_name | aut_genre
Stephen King | 1
...
...
Author 4 | 2
And a genre table :
t_genre
genre_id | genre_name
1 | Horror
2 | Comedy
...
...
I've tried to use a GROUP BY but I can't find how to display the names of the category and organize my list:
SELECT t_author.aut_name, t_author.aut_genre
FROM t_author
LEFT JOIN t_genre ON t_author.aut_genre = t_genre.genre_id
GROUP BY t_genre.aut_genre
So, using MySQL and PDO, is there a way to select and fetch all the authors and display it by categories?
No need to say that I'm not looking for a code but just a clue because I don't even see how to describe it. I mean, is GROUP BY the right statement to use?
EDIT 1 :
Apparently, I was looking for something like this :
SELECT t_author.aut_name, t_author.aut_slug, t_genre.genre_name
FROM t_author
LEFT JOIN t_genre ON t_author.genre_id = t_genre.genre_id
But it displays:
Horror
Stephen King
Horror
Author 2
Comedy
Author 4
Horror
Author 3
I perfectly understand why but I can't find how to display it like below:
Horror
Stephen King
Author 2
Author 3
...
Comedy
Author 4
Author 5
...
Answer
HtmHell provided me a good way to do this with a 2D array. For my 3D array, I edited his code like this:
foreach($result as $author=> $slug) {
$authorsByGenre[$slug['genre_name']][] = array($slug['aut_name'] => $slug['aut_slug']);
}
return $authorsByGenre;

How about something like this:
$authorsByGenre = [];
$results = $db->query("
SELECT t_author.aut_name, t_genre.genre_name
FROM t_genre
JOIN t_author
ON t_author.aut_genre = t_genre.genre_id
")->fetchAll();
foreach ($results as $data) {
$authorsByGenre[$data['genre_name']][] = $data['aut_name'];
}
print_r($authorsByGenre);

SELECT GROUP_CONCAT(t_author.aut_name) as authors, t_genre.genre_name as genre FROM t_author
LEFT JOIN t_genre ON t_author.aut_genre = t_genre.genre_id
GROUP BY t_author.aut_genre
This will output authors as author1,author2,author3 in column 1 and genre column with genre_name so you can split or explode authors or whatever

Like it was suggested in the comments, PDO::FETCH_GROUP is the answer to your question. Dunno why you ignored it
$sql = "SELECT genre_name, aut_name, aut_slug
FROM t_author a LEFT JOIN t_genre g ON a.genre_id = g.genre_id";
$authorsByGenre = $db->query($sql)->fetchAll(PDO::FETCH_GROUP);
print_r($authorsByGenre);

Related

How should be my mysql table structure?

This is what I want:
Users will send one or two values in my website and I will store them in two variables $genres1 and $genres2.
Like: If user sends, Action, then my code will show all movies with Action genres. If user sends Action+Crime, then my table will fetch all movies with Action+Crime.
Got it?
My current table structure is one to many relationship, like this
tmdb_id movie_title
-----------------------------
1 Iron man
2 Logan
3 Batman
4 The hangover
tmdb_id genres
-----------------------------
1 Action
1 Crime
2 Drama
2 Action
3 Crime
3 Action
4 Comedy
4 Drama
But the problem here is, I can't achieve what I explained above with this.
2nd option: I make a single table like this:
movie_tile genres1 genres2 genres3 genres4
----------------------------------------------------
Logan Action Crime Drama Null
Iron man Action Crime Null Null
And I can do what, I want with this single line:
SELECT * FROM movies WHERE (genres1='$genres1' or genres2='$genres1' orgenres1='$genres3' or genres3='$genres1')
Any other option?
use a table width genres
and use an other table connecting the movie to any genre
-----
movieid title
-----
1 Logan
2 Smurf
-----
-----
genreid genre
-----
1 animated
2 blue people
-----
-----
movieid genreid
-----
1 1
2 1
2 2
-----
that way you won't be limited to 4 genres per movie
now I read your question better.
That's what you do, but you put left out the genre-table.
The 2nd option is bad, as you limit yourself to only 4 categories
Is this connected to PHP? I think is easiest to solve this further by a join query, sorted by movie and a loop in PHP
you want all movies where (by user request) the genres are both Crime And Action?
SELECT mg.movieid, count(1), m.title
FROM movies_genres mg
JOIN movies m ON m.movieid mg.movieid
WHERE mg.genreid = 1 OR mg.genreid =3
group by mg.movieid, m.title
HAVING COUNT(1) = 2
edit: see other genres as well
SELECT movies.movieid,movies.title, genres.genre
FROM movies
JOIN movie_genre mg ON mg.movieid = movies.movieid
JOIN genres on genres.genreid = mg.genreid
WHERE movie.movieid IN (
SELECT mg.movieid
FROM movies_genres mg
WHERE mg.genreid = 1 OR mg.genreid =3
GROUP BY mg.movieid
HAVING COUNT(1) = 2
)
forgot to mention: count = 2, means you gave 2 genreid's to find. This could also be 1, 3 or 25
select distinct a.tmdb_id, a.movie_tittle
from movie_tittle a inner join genre_tittle b
on a.tmdb_id = b.tmdb_id
where b.genres in ('Action', 'Crime')
Based on your comment, try this :
SELECT
a.tmdb_id, a.movie_tittle
FROM
movie_tittle a inner join genre_tittle b
ON
a.tmdb_id = b.tmdb_id
WHERE
b.genres in ('Action', 'Crime')
GROUP BY
a.tmdb_id, a.movie_tittle
HAVING
count(a.tmdb_id) = 2
tmdb_id and genres in table genre_tittle should not duplicated. Make it as primary key.
But the problem here is, I can't achieve what I explained above with [the first two tables]
Yes, you can. Assuming the two tables are called movies and movie_genres, you can select the movies which have both tags using:
SELECT movie_title FROM movies
JOIN movie_genres genre1 USING (tmdb_id)
JOIN movie_genres genre2 USING (tmdb_id)
WHERE genre1.genres = 'Action'
AND genre2.genres = 'Crime'
See it for yourself here.
try something like this :
tableA
Movie_ID Movie_title
1 Iron man
2 Logan
3 Batman
4 The hangover
tableB
Genre_ID Genre_title
1 Action
2 Crime
3 Drama
4 Comedy
tableC
ID Movie_ID Genre_ID
1 1 1
2 1 2
3 2 2
4 2 3
query :
Select A.Movie_title,B.Genre_title
from tableC C
inner join tableA A on A.Movie_ID = C.Movie_ID
inner join tableB B on B.Genre_ID = C.Genre_ID
where
C.Genre_ID in (IFNULL(val1,0),IFNULL(val2,0))
you should make a relational table to solve you issues like so
movie table
movie_id movie_name genre_id
1 alien 2
2 logan 1
3 ps i love you 4
4 click 3
then you will need a genre table
genre table
genre_id genre_type
1 action
2 sci fi
3 comedy
4 romance
then your select would link the to tables
function get_movies_by_genre($genre_id) {
global $MySQLiConnect;
$query = '
SELECT *
FROM movies m
INNER JOIN genre g ON (g.genre_id = m.genre_id)
WHERE g.genre_id = ?
';
$stmt = $DBConnect->stmt_init();
if ($stmt->prepare($query)) {
$stmt->bind_param("i", $genre_id);
$stmt->execute();
$result = $stmt->get_result();
$rows = $result->fetch_all(MYSQLI_ASSOC);
$stmt->close();
}
return $rows;
}
or
function get_movies_by_genre($genre_id) {
global $MySQLiConnect;
$query = '
SELECT *
FROM movies m
INNER JOIN genre g ON (g.genre_id = m.genre_id)
WHERE g.genre_name = ?
';
$stmt = $DBConnect->stmt_init();
if ($stmt->prepare($query)) {
$stmt->bind_param("i", $genre_id);
$stmt->execute();
$result = $stmt->get_result();
$rows = $result->fetch_all(MYSQLI_ASSOC);
$stmt->close();
}
return $rows;
}
This is the base function to get you all information from the movie table depending on which genre id you send to it.
as for multiple ids you can then run the function through a foreach loop for as many genre_ids as you need and then display them as you need.
I hope this helps.

how to loop through multiple categories in sigle row using php and mysql

i have a database name category
parent_cat cat_id title
0 1 fruit
0 2 vehicle
0 3 goods
1 4 sour
1 5 sweet
1 6 mixed
2 7 sedan
2 8 hatchback
2 9 car
and i store a object in database table name product
obj_name parent_cat sub_id
mango 1 4,5,
maruti 2 7,8,9
bmw 2 7,9
i want to join the two table to show the data so i need to pass the parameter in URL ie. ?obj=vehicle i got by doing sql query
SELECT category.cat_id,category.title,product.parent_cat,product.obj_name
FROM category, product
WHERE category.cat_id=product.parent_cat
AND category.title='$title' --is a difined get variable
if title=fruit i got "mango" if title=vehicle i got maruti and bmw
i want to know if title=sedan or title=car then how can i get maruti and bmw
through loop any solution
You might want to use a LEFT JOIN query, if you have comma separated values for title use IN()
SELECT a.cat_id, a.title, b.parent_cat, b.obj_name
FROM product b
LEFT JOIN category a
ON a.cat_id = b.parent_cat
WHERE a.title IN($title);
Try this:
SELECT category.cat_id, category.title, product.obj_name, product.parent_cat, product.sub_id FROM category
LEFT JOIN product ON category.cat_id = product.parent_cat OR category.cat_id LIKE '%product.sub_id%'
WHERE category.title LIKE '%$title%'
Use LIKE instead of = when you're not sure of the exact data you're comparing or looking for.
[UPDATE]
SELECT category.cat_id, category.title, product.obj_name, product.parent_cat, product.sub_id FROM product
LEFT JOIN category ON (product.parent_cat = category.cat_id OR product.sub_id LIKE '%category.cat_id%') AND category.title LIKE '%$title%'
I'm joining the table in wrong direction, sorry for that.

how can select data from two tables in php

I have two tables news and topics
news topics
id title text id title text
--- ----- ---- --- ----- ----
1 abc aa 1 hgd hh
2 def bb 2 ddf ff
3 gfs cc 3 gty gg
4 sdfv dd 4 bbc tt
i want to select title the two tables
i tried this code but it sin't work
<?
$select_newtopics = $mysqli->query("select * from news,arts order by id desc");
$num_newtopics = $select_newtopics->num_rows;
while ($rows_newtopics = $select_newtopics->fetch_array(MYSQL_ASSOC)){
$id_newtopics = $rows_newtopics ['id'];
$title_newtopics = $rows_newtopics ['title'];
echo $title_newtopics."<br>";
}
?>
Assuming you want a result set that contains all the (unique) titles from both tables, regardless of whether or not the tables are related in any way...
SELECT title FROM news
UNION
SELECT title FROM topics
See MySQL's UNION documentation for more details, options, and specifics.
To display the results, it's mostly the same as your previous code:
$select_newtopics = $mysqli->query("SELECT title FROM news
UNION
SELECT title FROM topics");
$num_newtopics = $select_newtopics->num_rows;
while ($row = $select_newtopics->fetch_array(MYSQL_ASSOC)) {
echo $row['title'] . '<br>';
}
Since I don't see a key tying the 2 tables together, you can use UNION reference google for additional info, example below:
SELECT title FROM news
UNION
SELECT title FROM topics;
Your table have to share an id for example added news_id to topics table to link the two table
news topics
id title text id title text news_id
--- ----- ---- --- ----- ---- -------
1 abc aa 1 hgd hh 1
2 def bb 2 ddf ff 2
3 gfs cc 3 gty gg 3
4 sdfv dd 4 bbc tt 4
Please update your database structure and you can use JOIN
<?
$select_newtopics = $mysqli->query("SELECT news.id AS newsId,
news.title AS newsTitle,
news.text AS newsText,
topics.id AS topicId,
topics.title AS topicTitle,
topics.text AS topictext
FROM topics
LEFT JOIN news ON topics.news_id = news.id
ORDER BY topics.id
DESC");
$num_newtopics = $select_newtopics->num_rows;
while ($rows_newtopics = $select_newtopics->fetch_array(MYSQL_ASSOC)){
$id_newtopics = $rows_newtopics ['topicId'];
$title_newtopics = $rows_newtopics ['topicTitle'];
echo $title_newtopics."<br>";
}
?>

comparing different columns and rows on the same table

We are making a simple database for our school programme. we have a table like this:
ID A B
1 John Stacey
2 Stacey Mark
3 Candice Rick
4 Stacey Rick
5 Rick Stacey
If we input Stacey's name, we display the number of rows where:
for every row (say, x and y)
rowX-ColumnA = rowY-ColumnB AND rowY-ColumnA = rowX-ColumnB
in this case, it should output:
2 rows:
4 Stacey Rick
5 Rick Stacey
Thanks! We have more than 100 students so we won't be able to do this manually. Again, I appreciate any hint.
Try this query my friend:
select t1.* from table1 t1
inner join table1 t2 on t1.A = t2.B and t1.B = t2.A;
SQL Fiddle
This will do it
SELECT p1.*
FROM People p1
INNER JOIN
People p2 ON p1.A=p2.B AND p1.B=p2.A
WHERE p1.A='Stacey' OR p1.B='Stacey'
See this SQLfiddle (SQL Server 2008)
Based on your example. I think you're probably looking for something like this:
select stu1.* from students stu1,
students stu2
where stu1.last_name = stu2.first_name
union
select stu1.* from students stu1,
students stu2
where stu1.first_name = stu2.last_name;
http://sqlfiddle.com/#!4/e9bbf/2/0
Above answer was based on your example of John Stacy , Stacy Rick.

Result display problem in php and mysql

A B C
P_id | name | add P_id | t_id t_id | paper
----------------- -------------- ------------------
1 sam ca 1 1 1 asdxa
2 john de 2 1 2 dgfv
3 sam jk 3 2 3 decgf
4 sam ca 4 3 4 ergvtr
Now I can easily make a search for Name 'sam' in Table A group by name, add. and It shows me result like,
sam ca
sam jk
I am using php and mysql. I want to do some additional task in this:-
--> Totalcount for the rows..Like
sam ca 2
sam jk 1
(I am not taking P_id here... just focus on name and add.)
--> Make a link on 2 and 1 (above). so if I click on it. It should displays the related papers on another html page from table C.
example: if I click on 2... then it should display asdxa and decgf.
--> Totalcount for the rows..Like
SELECT `name`, `add`, count(`add`) FROM `A` WHERE (`name` = 'sam') GROUP BY `add`;
As for the linking, you just link to the page with that ID, and have your php script get the data from the given id in the C table.
To select all matching occurences while searching for a name:
SELECT `A`.`name` AS name, `A`.`P_id` AS aid, `C`.`t_id` AS cid, `C`.`paper` AS paper
FROM `A` , `C`
WHERE (
`A`.`name` = 'sam'
)
AND (
`A`.`P_id` = `C`.`t_id`
)
result:
name aid cid paper
sam 1 1 qwertyui
sam 3 3 zxcvbn
sam 4 4 uytrewq
sam 5 5 hfdsa
Which matches the test tables I did in my local environment
Try to use for the first task
$pdo = new PDO(....);
$result = $pdo->query('SELECT name, add, count(*) from table where name='sam' group by add;')->fetchAll();
if ($result) {
foreach($result as $row) {
......
}
}
//second
$sql = 'select paper from tableA a inner join TableB b on a.P_id=b.P_id inner join Tablec c inner join b.t_id = c.t_id where a.p_id=2';
//repeat previous statements

Categories