左连接右表mysql中的空行

时间:2013-08-21 16:00:04

标签: mysql sql join

我有餐馆和订单表,在订单表中我有restaurant_idstatusdate字段 - 每天我在订单表中保存一行。如果有一天没有订单 - 这意味着订单表中当天没有行。

我希望在日历上显示每个餐厅当前月份的数据,根据这两个不同的条件。

1) in first case show only those restaurants that have at least one free 
day during this month(which means for this month at least one date is missing in orders table).

2) in second case show only those restaurants that are free for today 
(which means there is no row for today in orders table)

对于这两种情况,如果条件满足,我应该获取当月的所有订单 - 这是棘手的部分。

通常使用左连接或内连接的反连接不会产生所需的结果。

感谢。

修改

输出应该是这样的

1)http://img826.imageshack.us/img826/3114/e6zt.png

2)http://img13.imageshack.us/img13/6397/44l0.png

1 个答案:

答案 0 :(得分:1)

这是今天所有免费餐厅的所有列表:

SELECT  r.`id`, r.`name`, o.`date`, o.`status`,  o.`id` order_id
FROM    restaurants r
        INNER JOIN orders o 
            ON r.id = o.restaurant_id
        LEFT JOIN
        (   SELECT  DISTINCT o2.Restaurant_ID
            FROM    orders o2
            WHERE   o2.date = DATE(CURRENT_TIMESTAMP)
        ) o2
            ON r.id = o2.restaurant_id
WHERE   o.Date >= DATE_FORMAT(CURRENT_TIMESTAMP ,'%Y-%m-01')
AND     o.Date <= DATE_FORMAT(DATE_ADD(CURRENT_TIMESTAMP, INTERVAL 1 MONTH) ,'%Y-%m-01')
AND     o2.Restaurant_ID IS NULL;

这简单地让今天所有的餐厅都有预订(子查询o2),然后排除这些餐厅:

AND     o2.Restaurant_ID IS NULL;

这是本月所有至少有一个免费日餐厅的所有房源:

SELECT  r.`id`, r.`name`, o.`date`, o.`status`,  o.`id` order_id
FROM    restaurants r
        INNER JOIN orders o 
            ON r.id = o.restaurant_id
            AND o.date BETWEEN '2013-08-10' AND '2013-08-31' 
        INNER JOIN
        (   SELECT  o2.Restaurant_ID
            FROM    orders o2
            WHERE   o2.Date >= DATE_FORMAT(CURRENT_TIMESTAMP ,'%Y-%m-01')
            AND     o2.Date <= DATE_FORMAT(DATE_ADD(CURRENT_TIMESTAMP, INTERVAL 1 MONTH) ,'%Y-%m-01')
            GROUP BY o2.Restaurant_ID
            HAVING COUNT(DISTINCT o2.Date) < DAY(DATE_ADD(DATE_FORMAT(DATE_ADD(CURRENT_TIMESTAMP, INTERVAL 1 MONTH) ,'%Y-%m-01'), INTERVAL -1 DAY))
        ) o2
            ON r.id = o2.restaurant_id
WHERE   o.Date >= DATE_FORMAT(CURRENT_TIMESTAMP ,'%Y-%m-01')
AND     o.Date <= DATE_FORMAT(DATE_ADD(CURRENT_TIMESTAMP, INTERVAL 1 MONTH) ,'%Y-%m-01');

诀窍是获得本月的天数:

DAY(DATE_ADD(DATE_FORMAT(DATE_ADD(CURRENT_TIMESTAMP, INTERVAL 1 MONTH) ,'%Y-%m-01'), INTERVAL -1 DAY))

然后将结果限制为比预订少的restaurant_id:

HAVING COUNT(DISTINCT o2.Date) < DAY(DATE_ADD(DATE_FORMAT(DATE_ADD(CURRENT_TIMESTAMP, INTERVAL 1 MONTH) ,'%Y-%m-01'), INTERVAL -1 DAY))

<强> Example of Both on SQL Fiddle