PSQL 左外连接不返回不匹配连接的值
PSQL left outer join not returning values for unmatched join
类似于 Left-Outer Join in Postgres Not Returning Values for Null ,但那里的解释并没有改善我的情况。
我的期望是,当未指定的方向(与指定的 left/right 相反)不匹配时,外连接保持指定的方向(左或右)不变,同时放置空值。我过去曾在另一个数据库上成功使用过它,但无法再访问示例代码。
这是我的玩具示例,可以正常工作:
with complete as (
select generate_series(
'2018-06-15'::date,
'2018-06-17'::date,
'1 day'::interval
)::date as date
), incomplete as (
select *
from (
values('2018-06-15'::date),('2018-06-17'::date)
) as foo(date)
)
select
complete.date as complete
, incomplete.date as incomplete
from complete
left outer join incomplete using(date)
;
结果符合预期:
complete | incomplete
------------+------------
2018-06-15 | 2018-06-15
2018-06-16 |
2018-06-17 | 2018-06-17
(3 rows)
现在使用真实数据做同样的事情:
with alldates as (
select
generate_series(
min(datetime::date),
max(datetime::date),
'1 day'::interval
)::date as date
from garagetime
), datadates as (
select distinct datetime::date as date
from garagetime
)
select
alldates.date as alldate
, datadates.date as datadate
from alldates
left outer join datadates using(date)
;
没有按预期工作:
alldate | datadate
------------+------------
2016-08-10 | 2016-08-10
2016-08-11 | 2016-08-11
2016-08-12 | 2016-08-12 -- skips right over 13..16
2016-08-17 | 2016-08-17 -- skips again
2016-08-22 | 2016-08-22
2016-08-23 | 2016-08-23
...
预期结果:
alldate | datadate
------------+------------
2016-08-10 | 2016-08-10
2016-08-11 | 2016-08-11
2016-08-12 | 2016-08-12
2016-08-13 | -- nulls, as expected
2016-08-14 |
2016-08-15 |
2016-08-16 |
2016-08-17 | 2016-08-17
2016-08-18 |
2016-08-19 |
2016-08-20 |
2016-08-21 |
2016-08-22 | 2016-08-22
2016-08-23 | 2016-08-23
...
我尝试切换联接 left/right,切换联接中指定 table 名称的顺序(尽管我非常有信心知道何时使用 "left" vs "right" 基于我试图获得的结果),使用 "ON alldates.date=datadates.date" 而不是 "USING(date)",将 "AS date" 列重命名为 "date" 以外的名称。
而不是这个:
select
alldates.date as alldate
, datadates.date as datadate
我也试过这个:
select
alldates.date as alldate
, case
when alldates.date=datadates.date then alldates.date
else null
end as datadate
还有这个:
select
alldates.date
, datadates.date
一旦我放弃连接,查询 returns 所有日期,但在那种情况下我看不到缺少哪些日期。
评论太长了。我怀疑它 工作正常,但结果与您期望的顺序不一致。
添加 order by
是否会按照您想要的顺序排列所有日期?
select alldates.date as alldate,
datadates.date as datadate
from alldates left outer join
datadates
using(date)
order by alldates.date;
类似于 Left-Outer Join in Postgres Not Returning Values for Null ,但那里的解释并没有改善我的情况。
我的期望是,当未指定的方向(与指定的 left/right 相反)不匹配时,外连接保持指定的方向(左或右)不变,同时放置空值。我过去曾在另一个数据库上成功使用过它,但无法再访问示例代码。
这是我的玩具示例,可以正常工作:
with complete as (
select generate_series(
'2018-06-15'::date,
'2018-06-17'::date,
'1 day'::interval
)::date as date
), incomplete as (
select *
from (
values('2018-06-15'::date),('2018-06-17'::date)
) as foo(date)
)
select
complete.date as complete
, incomplete.date as incomplete
from complete
left outer join incomplete using(date)
;
结果符合预期:
complete | incomplete
------------+------------
2018-06-15 | 2018-06-15
2018-06-16 |
2018-06-17 | 2018-06-17
(3 rows)
现在使用真实数据做同样的事情:
with alldates as (
select
generate_series(
min(datetime::date),
max(datetime::date),
'1 day'::interval
)::date as date
from garagetime
), datadates as (
select distinct datetime::date as date
from garagetime
)
select
alldates.date as alldate
, datadates.date as datadate
from alldates
left outer join datadates using(date)
;
没有按预期工作:
alldate | datadate
------------+------------
2016-08-10 | 2016-08-10
2016-08-11 | 2016-08-11
2016-08-12 | 2016-08-12 -- skips right over 13..16
2016-08-17 | 2016-08-17 -- skips again
2016-08-22 | 2016-08-22
2016-08-23 | 2016-08-23
...
预期结果:
alldate | datadate
------------+------------
2016-08-10 | 2016-08-10
2016-08-11 | 2016-08-11
2016-08-12 | 2016-08-12
2016-08-13 | -- nulls, as expected
2016-08-14 |
2016-08-15 |
2016-08-16 |
2016-08-17 | 2016-08-17
2016-08-18 |
2016-08-19 |
2016-08-20 |
2016-08-21 |
2016-08-22 | 2016-08-22
2016-08-23 | 2016-08-23
...
我尝试切换联接 left/right,切换联接中指定 table 名称的顺序(尽管我非常有信心知道何时使用 "left" vs "right" 基于我试图获得的结果),使用 "ON alldates.date=datadates.date" 而不是 "USING(date)",将 "AS date" 列重命名为 "date" 以外的名称。
而不是这个:
select
alldates.date as alldate
, datadates.date as datadate
我也试过这个:
select
alldates.date as alldate
, case
when alldates.date=datadates.date then alldates.date
else null
end as datadate
还有这个:
select
alldates.date
, datadates.date
一旦我放弃连接,查询 returns 所有日期,但在那种情况下我看不到缺少哪些日期。
评论太长了。我怀疑它 工作正常,但结果与您期望的顺序不一致。
添加 order by
是否会按照您想要的顺序排列所有日期?
select alldates.date as alldate,
datadates.date as datadate
from alldates left outer join
datadates
using(date)
order by alldates.date;