[英]LEFT OUTER JOIN with IS NULL
我在LEFT OUTER JOIN链上仅能处理90%的情况。
days:
id, date_value
1, 2017-01-01
2, 2017-01-02
3, 2017-01-03
periods:
id, starts_on, ends_on, name, federal_state_id, country_id
1, 2017-01-01, 2017-01-01, Test1, 1, NULL
2, 2017-01-03, 2017-01-03, Test2, 2, NULL
slots:
id, days_id, periods_id
1, 1, 1
2, 3, 2
SELECT days.date_value, periods.name, periods.federal_state_id
FROM days
LEFT OUTER JOIN slots ON (days.id = slots.day_id)
LEFT OUTER JOIN periods ON (slots.period_id = periods.id)
WHERE days.date_value >= '2017-01-01' AND
days.date_value <='2017-01-03' AND
(periods.id IS NULL OR periods.country_id = 1 OR
periods.federal_state_id = 1)
ORDER BY days.date_value;
2017-01-01, Test1, 1
2017-01-02, NULL, NULL
但我想得到这个结果:
2017-01-01, Test1, 1
2017-01-02, NULL, NULL
2017-01-03, NULL, NULL
据我了解,由于最后一个条目的federal_state_id
periods.id IS NULL
不匹配,因为存在period #2
的federal_state_id
为2
。
如何更改SQL查询以获取所需的结果?
如果将期间条目上的条件移至加入条件,则它们将不属于与槽加入的集合,从而为name
和federal_state_id
产生所需的NULL
。 因此,将要加入的集合将仅包含:
periods:
id, starts_on, ends_on, name, federal_state_id, country_id
1, 2017-01-01, 2017-01-01, Test1, 1, NULL
这样,可以返回每个日期输入(范围内的条件除外)。 查询将如下所示:
SELECT
days.date_value,
periods.name,
periods.federal_state_id
FROM days
LEFT OUTER JOIN slots
ON (days.id = slots.day_id)
LEFT OUTER JOIN periods
ON (slots.period_id = periods.id) AND
((periods.country_id = 1 OR
periods.federal_state_id = 1))
WHERE
days.date_value >= '2017-01-01' AND
days.date_value <='2017-01-03'
ORDER BY
days.date_value;
请注意,不再需要conditions.id periods.id IS NULL
条件,因为将条件套用到仅包含时隙和时间段的集合,其中每个时间段条目都是主键,因此每个id条目将具有一个id值。 并且,由于插槽和期间由左连接插槽连接,因此不会删除期间表中不匹配的内容。
在您的原始查询中,您首先加入了period的所有条目(如果id匹配),然后删除了所有没有所需country_id
或federal_state_id
。 这将删除period
有匹配但不符合条件的日期。
我总是建议格式化SQL语句。 错误更容易发现。
将条件移动到联接,例如:
SELECT days.date_value
,periods.name
,periods.federal_state_id
FROM dbo.days
LEFT OUTER JOIN dbo.slots
ON days.id = slots.days_id
LEFT OUTER JOIN dbo.periods
ON slots.periods_id = periods.id
AND (
periods.country_id = 1
OR periods.federal_state_id = 1
)
WHERE days.date_value >= '2017-01-01'
AND days.date_value <='2017-01-03'
ORDER BY days.date_value
;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.