假设您有一个返回如下记录集的查询:
Date | Code | Val 1 | Val 2
1/1/2016 A 1 2
1/1/2016 B 3 4
1/2/2016 A 5 6
1/2/2016 B 7 8
1/2/2016 C 9 10
第二个表包含" Code"的所有可能值。来自子查询:
Code
A
B
C
D
如何将两个集合连接起来,以便在第一个表中为每个日期的第二个表中的每个缺少的代码添加一个记录。在上面的示例中,结果查询应为:
Date | Code | Val 1 | Val 2
1/1/2016 A 1 2
1/1/2016 B 3 4
1/1/2016 C NULL NULL
1/1/2016 D NULL NULL
1/2/2016 A 5 6
1/2/2016 B 7 8
1/2/2016 C 9 10
1/2/2016 D NULL NULL
“代码”列上的外部联接适用于一天,但由于日期未包含在第二个集(或联接)中,因此在应用于跨越多个日期的集时,它不起作用。
答案 0 :(得分:1)
示例数据:
CREATE TABLE #temp (DateField DATE , Code CHAR , Val1 INT, Val2 INT)
INSERT INTO #temp
VALUES
('1/1/2016','A','1','2'),
('1/1/2016','B','3','4'),
('1/2/2016','A','5','6'),
('1/2/2016','B','7','8'),
('1/2/2016','C','9','10')
CREATE TABLE #Code (Code CHAR )
INSERT INTO #Code
VALUES('A'),
('B'),
('C'),
('D')
查询:
查询:
WITH CTE AS ( SELECT *
FROM (SELECT DISTINCT DateField
FROM #temp) AS A CROSS JOIN
#Code AS C
)
SELECT C.*,t.Val1,t.Val2
FROM CTE AS C LEFT OUTER JOIN
#temp AS t ON c.Code=t.Code AND c.DateField=t.DateField
结果:
答案 1 :(得分:1)
您没有说您正在使用哪个数据库;如果您没有可用的CTE,您也可以使用Calendar
表。
我假设您的数据是Orders
的表格,只是为了给表格命名。
CREATE TABLE Orders
(order_date date
,code varchar(1)
,val_1 int
,val_2 int);
INSERT INTO Orders
([order_date], [code], [val_1], [val_2])
VALUES
('2016-01-01 00:00:00', 'A', 1, 2),
('2016-01-01 00:00:00', 'B', 3, 4),
('2016-01-02 00:00:00', 'A', 5, 6),
('2016-01-02 00:00:00', 'B', 7, 8),
('2016-01-02 00:00:00', 'C', 9, 10);
CREATE TABLE Codes(code CHAR(1));
INSERT INTO Codes(code) VALUES
('A'),
('B'),
('C'),
('D');
CREATE TABLE Calendar(calendar_date DATE);
INSERT INTO Calendar(calendar_date) VALUES
('1/1/2016'),
('1/2/2016')
然后,您可以加入这些内容以获取每天的所有codes
SELECT calendar_date, T.code, val_1, val_2
FROM
(SELECT calendar_date, code FROM Codes CROSS JOIN Calendar) AS T
LEFT JOIN Orders ON T.calendar_date = Orders.order_date
AND T.code = Orders.code
ORDER BY calendar_date, T.code
查询结果
calendar_date code val_1 val_2
------------- ---- ----- -----
"2016-01-01" "A" "1" "2"
"2016-01-01" "B" "3" "4"
"2016-01-01" "C" "NULL" "NULL"
"2016-01-01" "D" "NULL" "NULL"
"2016-01-02" "A" "5" "6"
"2016-01-02" "B" "7" "8"
"2016-01-02" "C" "9" "10"
"2016-01-02" "D" "NULL" "NULL"
日历表的一个优点是,当您希望使用所有日期和代码填充结果时,即使主表中没有匹配的行也是如此。例如,添加另一个日期会产生结果
calendar_date code val_1 val_2
------------- ---- ----- -----
"2016-01-01" "A" "1" "2"
"2016-01-01" "B" "3" "4"
"2016-01-01" "C" "NULL" "NULL"
"2016-01-01" "D" "NULL" "NULL"
"2016-01-02" "A" "5" "6"
"2016-01-02" "B" "7" "8"
"2016-01-02" "C" "9" "10"
"2016-01-02" "D" "NULL" "NULL"
"2016-01-03" "A" "NULL" "NULL"
"2016-01-03" "B" "NULL" "NULL"
"2016-01-03" "C" "NULL" "NULL"
"2016-01-03" "D" "NULL" "NULL"
答案 2 :(得分:1)
使用cross join
和left join
:
select d.date, c.code, q.val1, q.val2
from (select distinct date from q) d cross join
codes c left join
q
on d.date = q.date and c.code = q.code;
cross join
生成所有行。 left join
会带来您感兴趣的值。
答案 3 :(得分:0)
尝试以下(SQL服务器)
DECLARE @dataTable TABLE (SampleDate DATE, Code CHAR(1), VALUE1 VARCHAR(10), VALUE2 VARCHAR(10));
INSERT INTO @dataTable (SampleDate, Code, VALUE1, VALUE2)
VALUES
('1/1/2016', 'C', 3, 2),
('1/1/2016', 'A', 3, 2),
('1/2/2016', 'A', 6, 4),
('1/5/2016', 'B', 9, 8);
DECLARE @Codes TABLE (Code CHAR(1));
INSERT INTO @Codes (Code)
VALUES
('A'),
('B'),
('C'),
('D');
WITH DateList AS (
SELECT CAST('2016-01-01' AS date) AS [DateKey]
UNION ALL
SELECT DATEADD(DAY,1,[DateKey])
FROM DateList
WHERE DATEADD(DAY,1,[DateKey]) <= CAST('2016-12-31' AS date))
SELECT s.DateKey, s.Code, dat.VALUE1, dat.VALUE2
FROM @dataTable dat RIGHT JOIN (
SELECT d.DateKey, c.Code
FROM @Codes c, DateList d) s
ON dat.Code = s.Code AND dat.SampleDate = s.DateKey
ORDER BY s.DateKey, s.Code
OPTION (MAXRECURSION 0)