LEFT JOIN查询返回多个结果

时间:2013-01-30 17:39:17

标签: mysql

我在下面的查询中查看了一个数据表,其中每一行都有ID,日期/时间和键操作(以及其他数据)。此表无法更改,无法控制。

查询发现Create操作(始终是第一个)的出现,拉出ID和创建日期/时间,然后拉出其他键操作的日期/时间(Add Info,Book Appt,Accept)in一行数据:

SELECT _create.ID AS ID, 
_create.`datetime` AS Create, 
_inform.`datetime` AS Add_Info,
_bookap.`datetime` AS Book_Appt,
_accept.`datetime` AS Accept,
FROM table AS _create
LEFT JOIN table AS _inform ON (_create.ID = _inform.ID AND _inform.action = 'Add Info')
LEFT JOIN table AS _bookap ON (_create.ID = _bookap.ID AND _bookap.action = 'Book Appt')
LEFT JOIN table AS _accept ON (_create.ID = _accept.ID AND _accept.action = 'Accept')
WHERE _create.action="Create"

所以我得到了类似的东西:

ID  -  Create Date - Inform Date - Bookap Date - Accept Date
1234   01/02/2013    02/02/2013    09/02/2013    10/02/2013 

这很有效。

但是,如果查询找到2个相同类型的事件,即同一ID的“Book Appt”(有时可能发生),则会为该ID提取两行数据。所以我得到了:

ID  -  Create Date - Inform Date - Bookap Date - Accept Date
1234   01/02/2013    02/02/2013    09/02/2013    10/02/2013 
1234   01/02/2013    02/02/2013    15/02/2013    10/02/2013     

我需要它忽略第二次出现并且每个ID只返回一行。或者,甚至更好地返回显示Bookap Date1和Bookap Date2的行。

有什么想法吗?

4 个答案:

答案 0 :(得分:2)

使用GROUP BY将记录分组到一行,min()选择最早的事件日期。

SELECT _create.ID AS ID, 
min(_create.`datetime`) AS Create, 
min(_inform.`datetime`) AS Add_Info,
min(_bookap.`datetime`) AS Book_Appt,
min(_accept.`datetime`) AS Accept,
FROM table AS _create
LEFT JOIN table AS _inform ON (_create.ID = _inform.ID AND _inform.action = 'Add Info')
LEFT JOIN table AS _bookap ON (_create.ID = _bookap.ID AND _bookap.action = 'Book Appt')
LEFT JOIN table AS _accept ON (_create.ID = _accept.ID AND _accept.action = 'Accept')
WHERE _create.action="Create"
GROUP BY _create.ID;

显示所有事件日期但仍然返回一行的快速而肮脏的方法是在上面的查询中使用group_concat()函数而不是min()。这会将多个datetime放入您的应用层需要解析的单个列中。

答案 1 :(得分:0)

当然,请在GROUP BY _create.ID条款后使用WHERE

答案 2 :(得分:0)

如果您想在一行中返回多个Book_Appt值,可以像这样使用GROUP_CONCAT

SELECT _create.ID AS ID, 
_create.`datetime` AS Create, 
_inform.`datetime` AS Add_Info,
GROUP_CONCAT(_bookap.`datetime`) AS Book_Appt,
_accept.`datetime` AS Accept,
FROM table AS _create
LEFT JOIN table AS _inform ON (_create.ID = _inform.ID AND _inform.action = 'Add Info')
LEFT JOIN table AS _bookap ON (_create.ID = _bookap.ID AND _bookap.action = 'Book Appt')
LEFT JOIN table AS _accept ON (_create.ID = _accept.ID AND _accept.action = 'Accept')
WHERE _create.action="Create"
GROUP BY `ID`

这将在您的案例中返回逗号分隔的日期时间值列表。

所以你的输出看起来像

ID  -  Create Date - Inform Date - Bookap Date      -       Accept Date
1234   01/02/2013    02/02/2013    09/02/2013,15/02/2013    10/02/2013 

答案 3 :(得分:0)

对于您的第一个问题(仅返回一行),我将使用ORDER BY子句对结果集进行排序,然后使用LIMIT 1表达式仅返回一行。