简体   繁体   English

如何加入日历表以获得主表中没有值的空值?

[英]How to join calendar table in order to get NULLs where there is no values in the main table?

Imagine I have a table for February with users and their COVID-19 quarantine isolation violations during a single day.想象一下,我有一张 2 月的表格,其中包含用户及其一天内的 COVID-19 隔离违规行为。 If the user didn't violate isolation whole day there is no such row in the table for this date.如果用户一整天都没有违反隔离,则该日期的表中没有这样的行。

user date       violations
1    2020-02-01 2
1    2020-02-03 1
1    2020-02-15 2
3    2020-02-04 1
3    2020-02-24 3

What type of join should I use for my query in order to show every day in February for each user and violations column value (null or 0 if there is no such row):我应该为我的查询使用什么类型的连接,以便为每个用户和违规列值显示 2 月的每一天(如果没有这样的行,则为 null 或 0):

user date       violations
1    2020-02-01 2
1    2020-02-02 NULL
1    2020-02-03 1
1    2020-02-04 NULL
...
1    2020-02-29 NULL
3    2020-02-01 NULL
3    2020-02-02 NULL
3    2020-02-03 NULL
3    2020-02-04 1
...
3    2020-02-29 NULL

I have a calendar table for February:我有一个二月的日历表:

date
2020-02-01
2020-02-02
...
2020-02-29

I tried a full outer join, but it works as I expected only for one user.我尝试了完整的外部联接,但它仅对一个用户按预期工作。

Use a cross join to generate the rows and then left join to bring in the existing data:使用cross join生成行,然后left join引入现有数据:

select c.date, u.user, v.violations
from calendar c cross join
     (select distinct user from violations) u left join
     violations v
     on c.date = v.date and u.user = v.user

If you have a separate table for users, then use that instead of the subquery for u .如果您有一个单独的用户表,则使用它而不是u的子查询。 After all, perhaps there are users who had no violations in February.毕竟,也许有用户在 2 月份没有违规。

If you have a separate table of users, then you need a cross join of calendar and users, and then left outer join to the violations table, as Gordon Linoff has already shown.如果你有一个单独的用户表,那么你需要一个日历和用户的交叉联接,然后左外联接到违规表,正如 Gordon Linoff 已经展示的那样。

However, if you don't have a table of users, and you must just pick them from the violations table, then you should use the partition outer join which exists exactly for this purpose:但是,如果您没有用户表,并且您必须从违规表中选择它们,那么您应该使用正是为此目的而存在的分区外连接

select v.user, c.date, v.violations
from   calendar c left outer join violations v
       PARTITION BY (v.user)                      -- this is what you must add
       on c.date = v.date
order  by user,date
;

The benefit is that you don't have to read the violations table twice.好处是您不必两次阅读违规表。

Note that DATE and USER and keywords and shouldn't be used as column names;请注意,不应将 DATE 和 USER 和关键字用作列名; I followed your lead with this, but your lead is not good.我在这方面跟随你的领导,但你的领导不好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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