Thursday, July 21, 2016

Left join returns too many rows. Need to combine certain columns

Saw this in a forum post on the MySQL web site...

Here's an example of the set up I'm using:
TITLES
id
name

DIRECTORS
id
name

ACTORS
id
name

MOVIES
id
movie_id
director_id

There can be several actors to a movie, so I use another join table:

MOVIES_ACTORS
id
movie_id
actor_id

This all works fine, except for one problem... i get several rows for one movie. So it comes out like this:

Star Wars - George Lucas - Harrison Ford
Star Wars - George Lucas - James Earl Jones
Star Wars - George Lucas - Yoda

King Kong - Peter Jackson - Jack Black

School of Rock - NULL - Jack Black

This is a problem because I don't want 3 results for Star Wars, I want one result row with 3 columns for the actors. Have three separate rows causes problems because:
1. If I were to limit the results to say, 3 I would only get Star Wars as a result.

2. When I display the results with PHP I have to build an elaborate array and loop through the result set 3 times just to avoid showing more than one result for the same movie in the list.

Here's my query:

SELECT
m.id, t.name, dir.name, act.name
FROM movies m
JOIN titles t ON t.id = m.title_id
LEFT OUTER JOIN directors dir ON dir.id = m.director_id
LEFT OUTER JOIN movies_actors ma ON ma.movie_id = m.id
LEFT OUTER JOIN actors a ON ma.actor_id = a.id



---------------------------------------------------------------
The solution is a GROUP_CONCAT on the terms you want to combine


SELECT m.id, t.name,
group_concat(dir.name) AS directors, group_concat(act.name) AS actors
FROM movies             AS m 
JOIN titles             AS t   ON t.id = m.title_id 
LEFT JOIN directors     AS dir ON dir.id = m.director_id 
LEFT JOIN movies_actors AS ma  ON ma.movie_id = m.id 
LEFT JOIN actors        AS a   ON ma.actor_id = a.id
GROUP BY t.name

It combines those columns as a comma-separated list.  You can also define a
separator...

GROUP_CONCAT(dir.name SEPARATOR '; ')
 

Monday, July 18, 2016

ESC characters in git diff output

You could change the pager to more, or just use the following to process the raw characters in less...

git config --global core.pager "less -r"

Monday, May 2, 2016

Reading from a file into MySQL

Basic load, there's lots more options for column delimiters, line delimiters, etc...

LOAD DATA INFILE '/tmp/mydata.txt' INTO TABLE Test;

Thursday, March 31, 2016

MySQL select on date range

Using date ranges in mysql...
 
select * from sale where date_begin between '2016-08-01' AND '2016-08-31';

Monday, March 28, 2016

Editing in hex mode in Vim

Native Vim doesn’t have a hex editing mode built in, however it is possible to edit a file in hex by converting the file back and forth using xxd. To do this, open your file in Vim and run :%!xxd. From here you can change the hex values and, when you’re done, run :%!xxd -r to convert back.

Tuesday, January 5, 2016

MySQL pager setting in ~/.my.cnf

I like setting the pager to less for the mysql client.  When I do it in my ~/.my.cnf file, thus...

[client]
pager=less

I get an error when running mysql dump...

mysqldump: unknown variable 'pager=less'

Turns out mysqldump also reads the [client] section of the file, as well as [mysqldump].  Using the following works...

[mysql]
pager=less

Tuesday, December 1, 2015

Autoformatting code in vim

To format a file in vim, gg=G (gg go to top of file, = format, G until end of file

More details here... http://stackoverflow.com/questions/11655383/vim-formatting-using-gg-g-with-xml