SQL Server-具有不存在的数据的完整结果

时间:2018-11-21 18:15:27

标签: sql sql-server

我有一个表,其中有所有客户,还有一个表,其中有所有他们的限制。

CUSTOMER

customer_id customer_name
1 name 1
2 name 2

CUSTOMER_RESTRICTIONS

rest_type day_of_week hour_start hour_stop customer_id

TYPE1  0  08:00  12:00  1
TYPE1  0  13:00  17:00  1
TYPE2  0  17:00  23:59  1

问题:当客户有限制时,我只有一个限制类型和一个客户的记录,这是我要构建的可视化中的问题。

即使没有限制,我也需要每一位客户,每一天和每种限制类型。在这种情况下,hour_start和hour_stop将为NULL。

对于所示表格,输出为

rest_type day_of_week hour_start hour_stop customer_id

TYPE1  0  08:00  12:00  1
TYPE1  0  08:00  12:00  1
TYPE1  1  NULL  NULL  1
TYPE1  2  NULL  NULL  1
TYPE1  3  NULL  NULL  1
TYPE1  4  NULL  NULL  1
TYPE1  5  NULL  NULL  1
TYPE1  6  NULL  NULL  1
TYPE1  1  NULL  NULL  1
TYPE1  2  NULL  NULL  1
TYPE1  3  NULL  NULL  1
TYPE1  4  NULL  NULL  1
TYPE1  5  NULL  NULL  1
TYPE2  0  NULL  NULL  1
TYPE2  1  NULL  NULL  1
TYPE2  2  NULL  NULL  1
TYPE2  3  NULL  NULL  1
TYPE2  4  NULL  NULL  1
TYPE2  5  NULL  NULL  1
TYPE2  6  NULL  NULL  1
TYPE1  0  NULL  NULL  2
TYPE1  1  NULL  NULL  2
TYPE1  2  NULL  NULL  2
TYPE1  3  NULL  NULL  2
TYPE1  4  NULL  NULL  2
TYPE1  5  NULL  NULL  2
TYPE1  6  NULL  NULL  2
TYPE2  0  NULL  NULL  2
TYPE2  1  NULL  NULL  2
TYPE2  2  NULL  NULL  2
TYPE2  3  NULL  NULL  2
TYPE2  4  NULL  NULL  2
TYPE2  5  NULL  NULL  2
TYPE2  6  NULL  NULL  2

我该如何实现?我什至无法开始建立此查询。

3 个答案:

答案 0 :(得分:1)

本质上,您需要从必须拥有的数据开始,然后将其加入可选数据。例如,如下所示:

select c.customer_id
    ,r.[rest_type]
    ,d.[day_of_week]
    ,r.[hour_start]
    ,r.[hour_stop]
from CUSTOMER c
cross apply (
    select 0 as day_of_week
    union all select 1
    union all select 2
    union all select 3
    union all select 4
    union all select 5
    union all select 6
) d 
left join CUSTOMER_RESTRICTIONS r on c.customer_id = r.customer_id and d.day_of_week = r.day_of_week

输出:

customer_id rest_type day_of_week hour_start hour_stop
----------- --------- ----------- ---------- ---------
1           TYPE1     0           08:00      12:00
1           TYPE1     0           13:00      17:00
1           TYPE2     0           17:00      23:59
1           NULL      1           NULL       NULL
1           NULL      2           NULL       NULL
1           NULL      3           NULL       NULL
1           NULL      4           NULL       NULL
1           NULL      5           NULL       NULL
1           NULL      6           NULL       NULL

如果只有rest_types类型,则没有它们的查找表,并且想要为每个显示一行,您可以这样做:

select c.customer_id
    ,t.[rest_type]
    ,d.[day_of_week]
    ,r.[hour_start]
    ,r.[hour_stop]
from CUSTOMER c
cross apply (
    select 0 as day_of_week
    union all select 1
    union all select 2
    union all select 3
    union all select 4
    union all select 5
    union all select 6
) d 
cross apply (
    select 'TYPE1' as rest_type
    union all select 'TYPE2'
) t
left join CUSTOMER_RESTRICTIONS r on c.customer_id = r.customer_id 
    and d.day_of_week = r.day_of_week 
    and t.rest_type = r.rest_type

答案 1 :(得分:0)

  (select rest_type, day_of_week,
   hour_start ,
   hour_stop 
   from table A
   where rest_type IS NOT NULL)
   Union
   (select rest_type, 
    day_of_week, 
    NULL ,NULL
    from table A 
     where rest_type IS NULL)
  

这是您想要的吗?

答案 2 :(得分:0)

首先,我不会像您一样存储休息类型,这是一个坏习惯,它应该是一个参考表!

您需要交叉申请以获取所有可能的组合,然后添加您拥有的值...

DECLARE @Customer TABLE (Id INT IDENTITY(1,1), Name NVARCHAR(100))
DECLARE @Rest TABLE (Id INT IDENTITY(1,1), Name NVARCHAR(100))
DECLARE @Restrictions TABLE (Id INT IDENTITY(1,1), RestID INT, CustomerID INT, Day_of_Week TINYINT, hour_start TIME, hour_end TIME)

INSERT INTO @Customer (NAME)
VALUES('JOHN'),('SUSAN')

INSERT INTO @Rest (NAME)
VALUES ('TYPE A'),('TYPE B')

INSERT INTO @Restrictions (RestID,CustomerID,Day_of_Week,hour_start,hour_end)
VALUES (1,1,0,'08:00','12:00'),
       (1,1,0,'13:00','17:00'),
       (1,2,0,'17:00','23:59')

;WITH DaysofWeek AS
(
    SELECT 0 AS dow
    UNION ALL
    SELECT dow+1
    FROM DaysofWeek
    WHERE dow<5
)

SELECT *
FROM @Customer C
CROSS APPLY @Rest R
CROSS APPLY DaysofWeek D
LEFT JOIN @Restrictions X
   ON X.Day_of_Week=D.dow
   AND X.CustomerID=C.Id
   AND X.RestID=R.Id
ORDER BY C.Id, D.dow, R.Id