Go Back   CodingForums.com > :: Server side development > MySQL

Before you post, read our: Rules & Posting Guidelines

Reply
 
Thread Tools Rate Thread
Enjoy an ad free experience by logging in. Not a member yet? Register.
Old 02-16-2013, 01:37 PM   PM User | #1
destas
New Coder

 
Join Date: Feb 2013
Posts: 32
Thanks: 10
Thanked 0 Times in 0 Posts
destas is an unknown quantity at this point
Get movie info and genres with 1 query

How can i get movie info from 'movies' table and genres of this movie from 'genres' table?

PHP Code:
$querynew         sprintf("SELECT * FROM `movies` ORDER BY `id` DESC LIMIT 0,4"); 
    
$resultnew         mysql_query($querynew); 
    
$TMPL_old         $TMPL$TMPL = array(); 
    
$template         = new template('movielist/toplist'); 
    
$new             ''
    while (
$row mysql_fetch_assoc($resultnew)) { 
        
$TMPL['genres'] = mysql_query("SELECT m.title as movie_title, GROUP_CONCAT(g.genre) AS genres FROM movies m 
INNER JOIN moviegenres mg ON (mg.movie_id = m.id) 
INNER JOIN genres g ON (g.id = mc.genre_id) 
GROUP BY m.id"
);
... 
destas is offline   Reply With Quote
Old 02-17-2013, 01:30 AM   PM User | #2
Old Pedant
Supreme Master coder!

 
Old Pedant's Avatar
 
Join Date: Feb 2009
Posts: 23,247
Thanks: 59
Thanked 3,998 Times in 3,967 Posts
Old Pedant is a name known to allOld Pedant is a name known to allOld Pedant is a name known to allOld Pedant is a name known to allOld Pedant is a name known to allOld Pedant is a name known to all
I don't get it. Why do you need that first query, at all???

What's wrong with simply
Code:
SELECT m.title, m.whatever, m.otherstuff, GROUP_CONCAT(g.genre) AS genres 
FROM movies m  
INNER JOIN moviegenres mg ON (mg.movie_id = m.id)  
INNER JOIN genres g ON (g.id = mc.genre_id)  
GROUP BY m.id
ORDER BY m.id
LIMIT 4
???
__________________
An optimist sees the glass as half full.
A pessimist sees the glass as half empty.
A realist drinks it no matter how much there is.
Old Pedant is online now   Reply With Quote
Users who have thanked Old Pedant for this post:
destas (02-20-2013)
Old 02-17-2013, 11:32 AM   PM User | #3
destas
New Coder

 
Join Date: Feb 2013
Posts: 32
Thanks: 10
Thanked 0 Times in 0 Posts
destas is an unknown quantity at this point
Doesn't show movies for me...
PHP Code:
    $querynew         sprintf("SELECT m.id, m.title, m.year GROUP_CONCAT(g.genre) AS genres 
FROM movies m  
INNER JOIN moviegenres mg ON (mg.movie_id = m.id)  
INNER JOIN genres g ON (g.id = mc.genre_id)  
GROUP BY m.id
ORDER BY m.id
DESC LIMIT 0,4"
);
    
$resultnew         mysql_query($querynew);
    
$TMPL_old         $TMPL$TMPL = array();
    
$template         = new template('movielist/newmovies');
    
$new             '';
    while (
$row mysql_fetch_assoc($resultnew)) {
    
        
$new .= $template->make();
    } 
Maybe something wrong with my tables?

Movies
PHP Code:
CREATE TABLE IF NOT EXISTS `movies` (
  `
idINT(11UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `
titleVARCHAR(128NOT NULL,
  `
yearYEAR NOT NULL,
  `
premiereDATE NOT NULL default '0000-00-00',
  `
imdbVARCHAR(10NOT NULL,
  `
addedTIMESTAMP NOT NULL default CURRENT_TIMESTAMP
ENGINE=MyISAM DEFAULT CHARSET=utf8
Genres
PHP Code:
CREATE TABLE IF NOT EXISTS `genres` (
  `
idINT(11UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `
genreVARCHAR(256NOT NULL
ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `genres` (`id`, `genre`) VALUES
(1'comedy'),
(
2'fantasy'),
(
3'horror'); 
Genres relationship
PHP Code:
CREATE TABLE IF NOT EXISTS `moviegenres` (
  `
idINT(11UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `
movie_idINT(10UNSIGNED NOT NULL,
  `
genre_idINT(10UNSIGNED NOT NULL,
   
FOREIGN KEY (`movie_id`) REFERENCES `movies`(`id`) ON DELETE CASCADE,
   
FOREIGN KEY (`genre_id`) REFERENCES `genres`(`id`) ON DELETE RESTRICT
ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `moviegenres` (`id`, `movie_id`, `genre_id`) VALUES
(111),
(
212),
(
313); 
destas is offline   Reply With Quote
Old 02-17-2013, 09:19 PM   PM User | #4
Old Pedant
Supreme Master coder!

 
Old Pedant's Avatar
 
Join Date: Feb 2009
Posts: 23,247
Thanks: 59
Thanked 3,998 Times in 3,967 Posts
Old Pedant is a name known to allOld Pedant is a name known to allOld Pedant is a name known to allOld Pedant is a name known to allOld Pedant is a name known to allOld Pedant is a name known to all
One *MAJOR* mistake, one typo.

When you use GROUP BY, you *MUST* specify *ALL* the columns from the SELECT that are NOT aggregate function results. MySQL allows you to omit columns, unlike any other DB (a huge mistake in my opinion), but then the results are *NOT* what you expect!

And look closely at INNER JOIN genres g ON (g.id = mc.genre_id)
Where did "mc" come from ???

So:
Code:
SELECT m.id, m.title, m.year GROUP_CONCAT(g.genre) AS genres  
FROM movies m   
INNER JOIN moviegenres mg ON (mg.movie_id = m.id)   
INNER JOIN genres g ON (g.id = mg.genre_id)   
GROUP BY m.id, m.title, m.year 
ORDER BY m.id 
DESC LIMIT 0,4
*PLEASE* learn to *TEST* your queries in a MySQL tool *BEFORE* using them in your PHP code! PHP gives horrible error diagnostics compared to a good tool.

*********

Other comments: There is really no point in using a FOREIGN KEY declaration if you will create MYISAM tables. MyISAM does *NOT* enforce referential integrity. If you want referential integrity, and especially if you want to use features such as ON DELETE CASCADE, you *must* use INNODB.

The ID column in your moviegenres table is pointless and useless. It adds nothing at all to the database capabilities.

A better declaration for that table would be:
Code:
CREATE TABLE moviegenres ( 
  movie_id INT UNSIGNED NOT NULL, 
  genre_id INT UNSIGNED NOT NULL, 
  PRIMARY KEY (movie_id, genre_id)
);
(And go ahead and add in the foreign keys, but only if you change the engine to INNODB.)
__________________
An optimist sees the glass as half full.
A pessimist sees the glass as half empty.
A realist drinks it no matter how much there is.
Old Pedant is online now   Reply With Quote
Users who have thanked Old Pedant for this post:
destas (02-20-2013)
Old 02-18-2013, 04:26 AM   PM User | #5
destas
New Coder

 
Join Date: Feb 2013
Posts: 32
Thanks: 10
Thanked 0 Times in 0 Posts
destas is an unknown quantity at this point
Did i did something wrong?

Mysql version: 5.5.20

PHP Code:
<?php
$con 
mysql_connect("localhost","root","");
mysql_select_db("imdb",$con);

$result mysql_query("SELECT m.id, m.title, m.year GROUP_CONCAT(g.genre) AS genres  
FROM movies m   
INNER JOIN moviegenres mg ON (mg.movie_id = m.id)   
INNER JOIN genres g ON (g.id = mg.genre_id)   
GROUP BY m.id, m.title, m.year 
ORDER BY m.id 
DESC LIMIT 0,4"
);

if (!
$result) {
    die(
mysql_error());
}
else
{
    while (
$row mysql_fetch_assoc($result))
    {
    
$results[] = $row;
        
$id $rows -> id;
        
$title $rows -> title;
        
        echo 
$id;
        echo 
$tile;
    }

}

mysql_free_result($result);

print_r(mysql_fetch_assoc($result));

mysql_close($con);
?>
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'GROUP_CONCAT(g.genre) AS genres FROM movies m INNER JOIN moviegenres mg O' at line 1
destas is offline   Reply With Quote
Old 02-18-2013, 04:34 PM   PM User | #6
Old Pedant
Supreme Master coder!

 
Old Pedant's Avatar
 
Join Date: Feb 2009
Posts: 23,247
Thanks: 59
Thanked 3,998 Times in 3,967 Posts
Old Pedant is a name known to allOld Pedant is a name known to allOld Pedant is a name known to allOld Pedant is a name known to allOld Pedant is a name known to allOld Pedant is a name known to all
Maybe because your "AS genres" conflicts with the table name "genres"??

You could try putting back ticks around the AS name: AS `genres`

I actually tried that query in my copy of MySQL 5.5 and it worked fine.
__________________
An optimist sees the glass as half full.
A pessimist sees the glass as half empty.
A realist drinks it no matter how much there is.
Old Pedant is online now   Reply With Quote
Users who have thanked Old Pedant for this post:
destas (02-20-2013)
Old 02-19-2013, 10:23 AM   PM User | #7
destas
New Coder

 
Join Date: Feb 2013
Posts: 32
Thanks: 10
Thanked 0 Times in 0 Posts
destas is an unknown quantity at this point
I get same error...
PHP Code:
$result mysql_query("SELECT m.id, m.title, m.year GROUP_CONCAT(g.genre) AS `genryes` 
FROM movies m   
INNER JOIN moviegenres mg ON (mg.movie_id = m.id)   
INNER JOIN `genryes` g ON (g.id = mg.genre_id)   
GROUP BY m.id, m.title, m.year 
ORDER BY m.id 
DESC LIMIT 0,4"
); 
destas is offline   Reply With Quote
Old 02-19-2013, 08:03 PM   PM User | #8
Old Pedant
Supreme Master coder!

 
Old Pedant's Avatar
 
Join Date: Feb 2009
Posts: 23,247
Thanks: 59
Thanked 3,998 Times in 3,967 Posts
Old Pedant is a name known to allOld Pedant is a name known to allOld Pedant is a name known to allOld Pedant is a name known to allOld Pedant is a name known to allOld Pedant is a name known to all
You are MISSING A COMMA between m.year and GROUP_CONCAT(...) !!!

Here is my test:
Code:
mysql> select * from movies;
+----+--------------------+------+------------+------+---------------------+
| id | title              | year | premiere   | imdb | added               |
+----+--------------------+------+------------+------+---------------------+
|  1 | kink kong          | 1939 | 0000-00-00 | xyz2 | 2013-02-17 16:00:52 |
|  2 | 2001 space odyssey | 1967 | 0000-00-00 | abc3 | 2013-02-17 16:01:51 |
|  3 | zombies            | 2012 | 0000-00-00 | jjj8 | 2013-02-17 16:01:51 |
+----+--------------------+------+------------+------+---------------------+
3 rows in set (0.00 sec)

mysql> select * from genres;
+----+---------+
| id | genre   |
+----+---------+
|  1 | comedy  |
|  2 | fantasy |
|  3 | horror  |
+----+---------+
3 rows in set (0.00 sec)

mysql> select * from moviegenres;
+----------+----------+
| movie_id | genre_id |
+----------+----------+
|        1 |        1 |
|        1 |        2 |
|        2 |        3 |
|        3 |        3 |
+----------+----------+
4 rows in set (0.01 sec)

mysql> SELECT m.id, m.title, m.year, GROUP_CONCAT(g.genre) AS genres
    -> FROM movies m
    -> INNER JOIN moviegenres mg ON (mg.movie_id = m.id)
    -> INNER JOIN genres g ON (g.id = mg.genre_id)
    -> GROUP BY m.id, m.title, m.year
    -> ORDER BY m.id
    -> DESC LIMIT 0,4;
+----+--------------------+------+----------------+
| id | title              | year | genres         |
+----+--------------------+------+----------------+
|  3 | zombies            | 2012 | horror         |
|  2 | 2001 space odyssey | 1967 | horror         |
|  1 | kink kong          | 1939 | fantasy,comedy |
+----+--------------------+------+----------------+
3 rows in set (0.00 sec)
And notice how the GROUP_CONCAT works for "kink kong". (It was a low budget spoof using a chimpanzee with strange sexual tastes.)
__________________
An optimist sees the glass as half full.
A pessimist sees the glass as half empty.
A realist drinks it no matter how much there is.

Last edited by Old Pedant; 02-19-2013 at 08:07 PM..
Old Pedant is online now   Reply With Quote
Users who have thanked Old Pedant for this post:
destas (02-20-2013)
Old 02-20-2013, 05:01 PM   PM User | #9
destas
New Coder

 
Join Date: Feb 2013
Posts: 32
Thanks: 10
Thanked 0 Times in 0 Posts
destas is an unknown quantity at this point
Stupid mistake

One more question. How to get genres + actors where genre name like... ?


PHP Code:
SELECT m.idm.titlem.yearGROUP_CONCAT(g.genre) AS genresGROUP_CONCAT(a.actor) AS actors 
FROM movies m 
INNER JOIN moviegenres mg ON 
(mg.movie_id m.id
INNER JOIN genres g ON (g.id mg.genre_id
INNER JOIN movieactors ma ON (ma.movie_id m.id
INNER JOIN actors g ON (a.id ma.actor_id
WHERE `genreLIKE '%%%s%%' 
GROUP BY m.title
LIMIT 
%d, %d;"; 

Last edited by destas; 02-20-2013 at 06:03 PM..
destas is offline   Reply With Quote
Old 02-20-2013, 07:11 PM   PM User | #10
Old Pedant
Supreme Master coder!

 
Old Pedant's Avatar
 
Join Date: Feb 2009
Posts: 23,247
Thanks: 59
Thanked 3,998 Times in 3,967 Posts
Old Pedant is a name known to allOld Pedant is a name known to allOld Pedant is a name known to allOld Pedant is a name known to allOld Pedant is a name known to allOld Pedant is a name known to all
??? That didn't work?

Maybe you need the table qualifier in there?

And why the excess of % characters?

WHERE g.genre LIKE '%s%'

But of course that will find *ANY* genre that has the letter "s" (or "S" -- SQL is not case sensitive) in it.
__________________
An optimist sees the glass as half full.
A pessimist sees the glass as half empty.
A realist drinks it no matter how much there is.
Old Pedant is online now   Reply With Quote
Old 02-25-2013, 01:47 PM   PM User | #11
destas
New Coder

 
Join Date: Feb 2013
Posts: 32
Thanks: 10
Thanked 0 Times in 0 Posts
destas is an unknown quantity at this point
I have another problem with genres page. Maybe you know php as well like mysql and can help me.

I need to get how many genre comedy have movies to make pages.

PHP Code:
    $genre_name urldecode(htmlEntities($_GET['q']));
    
$page_query mysql_query('SELECT COUNT(id), `genre` FROM `genres` WHERE `genre` LIKE "'.$genre_name.'"');
    
    
$pages = @ceil(mysql_result($page_query0) / $MovieListPerPage);
    
$page = (isSet($_GET['page']) AND (int)$_GET['page'] > 0) ? (int)$_GET['page'] : 1;
    
$start = ($page 1) * $MovieListPerPage
And another question:
PHP Code:
    $queryid 'SELECT * FROM `genres` WHERE `genre` LIKE "'.$genre_name.'"';
    if (
mysql_fetch_row(mysql_query($queryid)) >= 1)
    {
        if (!empty(
$genre_name))
        {
            if ( isSet(
$genre_name[1]) ) {
                
$query "SELECT m.id, m.title, m.year, GROUP_CONCAT(g.genre) AS genres, GROUP_CONCAT(a.actor) AS actors 
                        FROM movies m 
                        INNER JOIN moviegenres mg ON (mg.movie_id = m.id) 
                        INNER JOIN genres g ON (g.id = mg.genre_id) 
                        INNER JOIN movieactors ma ON (ma.movie_id = m.id) 
                        INNER JOIN actors a ON (a.id = ma.actor_id) 
                        WHERE `genre` LIKE '%s' 
                        ORDER BY m.title
                        LIMIT %d, %d;"
;
            } else {
                
$query "SELECT m.id, m.title, m.year, GROUP_CONCAT(g.genre) AS genres, GROUP_CONCAT(a.actor) AS actors 
                        FROM movies m 
                        INNER JOIN moviegenres mg ON (mg.movie_id = m.id) 
                        INNER JOIN genres g ON (g.id = mg.genre_id) 
                        INNER JOIN movieactors ma ON (ma.movie_id = m.id) 
                        INNER JOIN actors a ON (a.id = ma.actor_id) 
                        WHERE `genre` LIKE '%s' AND char_length(genre) >= 3
                        ORDER BY m.title
                        LIMIT %d, %d;"
;
            }
            
$query         sprintf($query$genre_name$start$MovieListPerPage);

            
$result     mysql_query($query);
            
$TMPL_old     $TMPL$TMPL = array();
            
$template     = new template('movielist/movielist');
            
$all         '';
            while ( 
$TMPL mysql_fetch_assoc($result) )
            {
                
$TMPL['moviegenres'] = str_replace(','', '$TMPL['genres']);
                
                
$all .= $template->make();
            } 
Why this code show me only one movie and only one genre?
example:
Genres: comedy, comedy, comedy, comedy, comedy, comedy, comedy
destas is offline   Reply With Quote
Old 02-25-2013, 05:07 PM   PM User | #12
Old Pedant
Supreme Master coder!

 
Old Pedant's Avatar
 
Join Date: Feb 2009
Posts: 23,247
Thanks: 59
Thanked 3,998 Times in 3,967 Posts
Old Pedant is a name known to allOld Pedant is a name known to allOld Pedant is a name known to allOld Pedant is a name known to allOld Pedant is a name known to allOld Pedant is a name known to all
Because you forgot the GROUP BY.

Look at my answer in post #4. You *MUST* group by ALL fields SELECTed other than the aggregate functions.

PERIOD.

MUST.

NO CHOICE.
__________________
An optimist sees the glass as half full.
A pessimist sees the glass as half empty.
A realist drinks it no matter how much there is.
Old Pedant is online now   Reply With Quote
Old 02-25-2013, 09:33 PM   PM User | #13
destas
New Coder

 
Join Date: Feb 2013
Posts: 32
Thanks: 10
Thanked 0 Times in 0 Posts
destas is an unknown quantity at this point
I add:
PHP Code:
GROUP BY m.title 
and now show movies. But how to fix genres? homepage with same code show genres nice...

PHP Code:
$TMPL['moviegenres'] = str_replace(','', '$TMPL['genres']); 
Why in genre page show one genre tons times?
destas is offline   Reply With Quote
Old 02-25-2013, 10:20 PM   PM User | #14
Old Pedant
Supreme Master coder!

 
Old Pedant's Avatar
 
Join Date: Feb 2009
Posts: 23,247
Thanks: 59
Thanked 3,998 Times in 3,967 Posts
Old Pedant is a name known to allOld Pedant is a name known to allOld Pedant is a name known to allOld Pedant is a name known to allOld Pedant is a name known to allOld Pedant is a name known to all
No. Go read post #4 *AGAIN AND AGAIN AND AGAIN*
Quote:
When you use GROUP BY, you *MUST* specify *ALL* the columns from the SELECT that are NOT aggregate function results. MySQL allows you to omit columns, unlike any other DB (a huge mistake in my opinion), but then the results are *NOT* what you expect!
__________________
An optimist sees the glass as half full.
A pessimist sees the glass as half empty.
A realist drinks it no matter how much there is.
Old Pedant is online now   Reply With Quote
Old 02-26-2013, 09:23 AM   PM User | #15
destas
New Coder

 
Join Date: Feb 2013
Posts: 32
Thanks: 10
Thanked 0 Times in 0 Posts
destas is an unknown quantity at this point
PHP Code:
SELECT m.idm.titlem.yearm.aam.bbm.ccm.ddGROUP_CONCAT(g.genre) AS genresGROUP_CONCAT(a.actor) AS actors 
PHP Code:
GROUP BY m.idm.titlem.yearm.aam.bbm.ccm.dd 
Same problem...
destas is offline   Reply With Quote
Reply

Bookmarks

Jump To Top of Thread


Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 12:06 AM.


Advertisement
Log in to turn off these ads.