Re: How to get hanging 1:M table rows as single column in main query?
GROUP_CONCAT() ? And group by id_fmr ? JW On Wed, Sep 29, 2010 at 2:38 PM, Daevid Vincent dae...@daevid.com wrote: Given three basic tables. An fmr table which has Field Maintenance Reports, a Seat table and a hanging or glue table to map Seats to FMRs. [See below] How do I get all the Seats to be in a single row with the FMR data? If I make this kind of query, they come in as separate rows: SELECT `id_fmr`, `fmr_number`, `fmr_system`, `fmr_station`, `created_ts`, `seat` FROM `fmr` JOIN `fmr_has_seat` USING (id_fmr) JOIN `dim_seat` USING (id_dim_seat) WHERE id_fmr = 3; id_fmr fmr_number fmr_system fmr_station created_ts seat -- -- -- --- --- 3 320237274 2333 JFK 2010-09-24 04:35:31 35C 3 320237274 2333 JFK 2010-09-24 04:35:31 35D 3 320237274 2333 JFK 2010-09-24 04:35:31 35E I want something more like: id_fmr fmr_number fmr_system fmr_station created_ts seat -- -- -- --- --- --- 3 320237274 2333 JFK 2010-09-24 04:35:31 35C,35D,35E Now, I'm going to be showing a few thousand FMR rows (and ideally their seats). What I do now is use PHP to pull the FMR records that match a certain criteria/filter. Then I pull in the entire dim_seats as an array and store it in a session since it's not going to change ever. Then I loop over all the id_fmr that I have pulled and look up in the fmr_has_seat table by id_fmr and implode() the seats from the session array. It saves me a few joins and gets the job done, but I keep feeling like there's a better way to do it. I'm thinking there's some magic with a subselect and concat or something in SQL, but then I wonder if that's any more efficient as mySQL still has to do two SELECTs per FMR row. This feels to me like a common problem and there must be an optimal mySQL way of doing it. Hanging tables of 1:M relationships are used everywhere. === == CREATE TABLE `fmr` ( `id_fmr` int(11) NOT NULL auto_increment, `fmr_number` varchar(32) NOT NULL default '', `fmr_system` smallint(6) default NULL, `fmr_station` varchar(4) NOT NULL default '', `created_ts` timestamp NOT NULL default CURRENT_TIMESTAMP, PRIMARY KEY (`id_fmr`) ) ENGINE=InnoDB id_fmr fmr_number fmr_system fmr_station created_ts -- -- -- --- --- 1 319235F2A 2333 JFK 2010-09-24 04:35:31 2 319235F29 2333 JFK 2010-09-24 04:35:31 3 320237274 2333 JFK 2010-09-24 04:35:31 --- 4 32023726D 2333 JFK 2010-09-24 04:35:31 5 32023725A 2333 JFK 2010-09-24 04:35:31 6 32023724F 2333 JFK 2010-09-24 04:35:31 7 320237241 2333 LAX 2010-09-24 04:35:31 8 32023723A 2333 LAX 2010-09-24 04:35:31 9 320237232 2333 JFK 2010-09-24 04:35:31 10 320237230 2333 JFK 2010-09-24 04:35:31 .... .. .. .. CREATE TABLE `fmr_has_seat` ( `id_fmr` int(11) NOT NULL auto_increment, `id_dim_seat` int(10) unsigned NOT NULL, PRIMARY KEY (`id_fmr`,`id_dim_seat`), KEY `id_dim_seat` (`id_dim_seat`), CONSTRAINT `fmr_has_seat_ibfk_1` FOREIGN KEY (`id_fmr`) REFERENCES `fmr` (`id_fmr`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `fmr_has_seat_ibfk_2` FOREIGN KEY (`id_dim_seat`) REFERENCES `dim_seat` (`id_dim_seat`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB id_fmr id_dim_seat -- --- 3 888 --- 3 889 --- 3 890 --- 4 422 4 423 4 551 4 552 4 553 5 420 5 550 5 628 5 629 5 706 5 707 5 811 ... ... CREATE TABLE `dim_seat` ( `id_dim_seat` int(10) unsigned NOT NULL auto_increment, `seat` varchar(4) default NULL, PRIMARY KEY (`id_dim_seat`), KEY `seat` (`seat`) ) ENGINE=InnoDB id_dim_seat seat --- -- ... ... 888 35C --- 889 35D --- 890 35E --- 891 35F 892 35G ... ... -- MySQL General Mailing List For list archives: http://lists.mysql.com/mysql To unsubscribe:http://lists.mysql.com/mysql?unsub=joh...@pixelated.net -- - Johnny Withers 601.209.4985 joh...@pixelated.net
RE: How to get hanging 1:M table rows as single column in main query?
BRILLIANT SELECT `id_fmr`, `fmr_number`, `fmr_system`, `fmr_station`, `created_ts`, GROUP_CONCAT(`seat`) FROM `fmr` JOIN `fmr_has_seat` USING (id_fmr) JOIN `dim_seat` USING (id_dim_seat) WHERE id_fmr = 3 GROUP BY id_fmr; id_fmr fmr_number fmr_system fmr_station created_ts group_concat(`seat`) -- -- -- --- --- 3 320237274 2333 JFK 2010-09-24 04:35:31 35C,35D,35E -Original Message- From: Johnny Withers [mailto:joh...@pixelated.net] Sent: Wednesday, September 29, 2010 1:35 PM To: Daevid Vincent Cc: MySQL Subject: Re: How to get hanging 1:M table rows as single column in main query? GROUP_CONCAT() ? And group by id_fmr ? JW On Wed, Sep 29, 2010 at 2:38 PM, Daevid Vincent dae...@daevid.com wrote: Given three basic tables. An fmr table which has Field Maintenance Reports, a Seat table and a hanging or glue table to map Seats to FMRs. [See below] How do I get all the Seats to be in a single row with the FMR data? If I make this kind of query, they come in as separate rows: SELECT `id_fmr`, `fmr_number`, `fmr_system`, `fmr_station`, `created_ts`, `seat` FROM `fmr` JOIN `fmr_has_seat` USING (id_fmr) JOIN `dim_seat` USING (id_dim_seat) WHERE id_fmr = 3; id_fmr fmr_number fmr_system fmr_station created_ts seat -- -- -- --- --- 3 320237274 2333 JFK 2010-09-24 04:35:31 35C 3 320237274 2333 JFK 2010-09-24 04:35:31 35D 3 320237274 2333 JFK 2010-09-24 04:35:31 35E I want something more like: id_fmr fmr_number fmr_system fmr_station created_ts seat -- -- -- --- --- --- 3 320237274 2333 JFK 2010-09-24 04:35:31 35C,35D,35E Now, I'm going to be showing a few thousand FMR rows (and ideally their seats). What I do now is use PHP to pull the FMR records that match a certain criteria/filter. Then I pull in the entire dim_seats as an array and store it in a session since it's not going to change ever. Then I loop over all the id_fmr that I have pulled and look up in the fmr_has_seat table by id_fmr and implode() the seats from the session array. It saves me a few joins and gets the job done, but I keep feeling like there's a better way to do it. I'm thinking there's some magic with a subselect and concat or something in SQL, but then I wonder if that's any more efficient as mySQL still has to do two SELECTs per FMR row. This feels to me like a common problem and there must be an optimal mySQL way of doing it. Hanging tables of 1:M relationships are used everywhere. == = == CREATE TABLE `fmr` ( `id_fmr` int(11) NOT NULL auto_increment, `fmr_number` varchar(32) NOT NULL default '', `fmr_system` smallint(6) default NULL, `fmr_station` varchar(4) NOT NULL default '', `created_ts` timestamp NOT NULL default CURRENT_TIMESTAMP, PRIMARY KEY (`id_fmr`) ) ENGINE=InnoDB id_fmr fmr_number fmr_system fmr_station created_ts -- -- -- --- --- 1 319235F2A 2333 JFK 2010-09-24 04:35:31 2 319235F29 2333 JFK 2010-09-24 04:35:31 3 320237274 2333 JFK 2010-09-24 04:35:31 --- 4 32023726D 2333 JFK 2010-09-24 04:35:31 5 32023725A 2333 JFK 2010-09-24 04:35:31 6 32023724F 2333 JFK 2010-09-24 04:35:31 7 320237241 2333 LAX 2010-09-24 04:35:31 8 32023723A 2333 LAX 2010-09-24 04:35:31 9 320237232 2333 JFK 2010-09-24 04:35:31 10 320237230 2333 JFK 2010-09-24 04:35:31 .... .. .. .. CREATE TABLE `fmr_has_seat` ( `id_fmr` int(11) NOT NULL auto_increment, `id_dim_seat` int(10) unsigned NOT NULL, PRIMARY KEY (`id_fmr`,`id_dim_seat`), KEY `id_dim_seat` (`id_dim_seat`), CONSTRAINT `fmr_has_seat_ibfk_1` FOREIGN KEY (`id_fmr`) REFERENCES `fmr` (`id_fmr`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `fmr_has_seat_ibfk_2` FOREIGN KEY (`id_dim_seat`) REFERENCES `dim_seat` (`id_dim_seat`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB id_fmr id_dim_seat -- --- 3 888 --- 3 889 --- 3 890 --- 4 422 4 423 4 551