简体   繁体   中英

MySQL Left Join return all data from left table?

I have two tables. I need to return a row from the left table even for options that are not in the right table.

Just for the example I have setup two sample tables. Here is the code to create tables & populate sample data:

CREATE TABLE `names` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) DEFAULT NULL,
  `optionid` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;

/*Data for the table `names` */

insert  into `names`(`id`,`name`,`optionid`) values (1,'name1',1),(2,'name2',2),(3,'name3',3),(4,'name4',4);

CREATE TABLE `options` (
  `tableid` int(11) NOT NULL AUTO_INCREMENT,
  `description` varchar(30) DEFAULT NULL,
  `optionid` int(11) DEFAULT NULL,
  PRIMARY KEY (`tableid`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1;

/*Data for the table `options` */

insert  into `options`(`tableid`,`description`,`optionid`) values (1,'option1',1),(2,'option2',1),(3,'option3',1),(4,'option1',2),(5,'option2',2),(6,'option1',3),(7,'option',3);

OK so I can left join which will return all rows from left and put NULL's on the right for any data not in the right table which is almost there.

Now if there is a matching value in the right table it only returns values that have data in the right table. now I need to return what I would class as the master record and then all the options from the right.

So if I run:

SELECT
      `names`.`id`
    , `names`.`name`
    , `names`.`optionid`
    , `options`.`description`
    , `options`.`optionid`

FROM
    `test`.`names`
    LEFT JOIN `test`.`options` 
        ON (`names`.`optionid` = `options`.`optionid`);

This returns:

   id   name    optionid    description optionid
1   name1   1           option1          1
1   name1   1           option2          1
1   name1   1           option3          1
2   name2   2           option1          2
2   name2   2           option2          2
3   name3   3           option1          3
3   name3   3           option           3
4   name4   4           NULL            NULL

This is exactly what I would expect but not what I want.

The Last row, ID 4 returns data with nulls because there is no data in the right table now I need to return this row for ID 1, 2 & 3 even though there is data in the right table, so even if there is data you still get the first record returned with NULL's from the left.

I know this doesn't make a whole lot of sense but for the project I am working on if there are related options the first record is classed as a Master/Shell record and the options are looped though in PHP however for the API I need to handle this in SQL which means returning the extra Shell record.

So what I would like the results to be are:

   id   name    optionid    description optionid
1   name1   1           NULL             NULL
1   name1   1           option1          1
1   name1   1           option2          1
1   name1   1           option3          1
2   name1   1           NULL             NULL
2   name2   2           option1          2
2   name2   2           option2          2
3   name1   1           NULL             NULL
3   name3   3           option1          3
3   name3   3           option           3
4   name4   4           NULL            NULL

Not sure if this is possibel but any feedback would be appreciated. Thanks in advance.

Can't think of an elegant way of doing it (hopefully someone else will suggest something), but possible to do it using a UNION:-

SELECT `names`.`id`, `names`.`name`, `names`.`optionid`, `options`.`description`, `options`.`optionid`
FROM `test`.`names`
LEFT JOIN `test`.`options` 
ON (`names`.`optionid` = `options`.`optionid`)
UNION
SELECT `names`.`id`, `names`.`name`, `names`.`optionid`, NULL, NULL
FROM `test`.`names`

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM