我有一个表格,我想加入日历表来制作时间序列,我这样做:
SELECT thedate AS Date
INTO #CALENDAR
FROM
(
SELECT *
FROM Sample.dbo.ExplodeDates('20120101','20121231') as d
) X
GO
CREATE INDEX D ON #CALENDAR(Date)
GO
SELECT Date, A, B, Value
FROM
(
SELECT StartDate, A, B, Value
FROM Sample.dbo.Values
) X
RIGHT OUTER JOIN #CALENDAR
ON Date = StartDate
ORDER BY Date
DROP TABLE #CALENDAR
GO
除非A和B的列包含NULL
,否则我会得到类似的结果:
2012-04-06 00:00:00.000 NULL NULL NULL
2012-04-07 00:00:00.000 NULL NULL NULL
2012-04-08 00:00:00.000 NULL NULL NULL
2012-04-09 00:00:00.000 A1 B1 4256
2012-04-10 00:00:00.000 A1 B1 4498
有没有办法可以得到这样的东西:
2012-04-06 00:00:00.000 A1 B1 0
2012-04-07 00:00:00.000 A1 B1 0
2012-04-08 00:00:00.000 A1 B1 0
2012-04-09 00:00:00.000 A1 B1 4256
2012-04-10 00:00:00.000 A1 B1 4498
我给了这个例子一对(A1,B1),但还有其他一些。有关如何实现这一目标的任何建议?
更新
更好的独立示例:
-- The explore dates function
USE Sample
GO
/****** Object: UserDefinedFunction [dbo].[ExplodeDates] Script Date: 01/18/2013 01:08:11 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ExplodeDates]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
BEGIN
execute dbo.sp_executesql @statement = N'CREATE FUNCTION [dbo].[ExplodeDates](@startdate datetime, @enddate datetime)
returns table as
return (
with
N0 as (SELECT 1 as n UNION ALL SELECT 1)
,N1 as (SELECT 1 as n FROM N0 t1, N0 t2)
,N2 as (SELECT 1 as n FROM N1 t1, N1 t2)
,N3 as (SELECT 1 as n FROM N2 t1, N2 t2)
,N4 as (SELECT 1 as n FROM N3 t1, N3 t2)
,N5 as (SELECT 1 as n FROM N4 t1, N4 t2)
,N6 as (SELECT 1 as n FROM N5 t1, N5 t2)
,nums as (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) as num FROM N6)
SELECT DATEADD(day,num-1,@startdate) as thedate
FROM nums
WHERE num <= DATEDIFF(day,@startdate,@enddate) + 1
);'
END
GO
SELECT thedate AS Date
INTO #CALENDAR
FROM
(
SELECT *
FROM Sample.dbo.ExplodeDates('20120101','20120103') as d
) X
GO
CREATE INDEX D ON #CALENDAR(Date)
GO
CREATE TABLE #TEMP(StartDate datetime, A varchar(50), B varchar(50), Value int)
INSERT INTO #TEMP VALUES('2012-01-01', 'A1', 'A1B1', 10)
INSERT INTO #TEMP VALUES('2012-01-02', 'A1', 'A1B2', 10)
INSERT INTO #TEMP VALUES('2012-01-02', 'A2', 'A2B2', 100)
-- SELECT all traffic values
SELECT Date, A, B, Value
FROM
(
SELECT StartDate, A, B, Value
FROM #TEMP
) X
RIGHT OUTER JOIN #CALENDAR
ON Date = StartDate
ORDER BY A, B, Date
DROP TABLE #CALENDAR
DROP TABLE #TEMP
GO
它现在给我的输出:
2012-01-03 00:00:00.000 NULL NULL NULL
2012-01-01 00:00:00.000 A1 A1B1 10
2012-01-02 00:00:00.000 A1 A1B2 14
2012-01-02 00:00:00.000 A2 A2B2 100
我想要的输出:
2012-01-01 00:00:00.000 A1 A1B1 0
2012-01-02 00:00:00.000 A1 A1B1 10
2012-01-03 00:00:00.000 A1 A1B1 0
2012-01-01 00:00:00.000 A1 A1B1 10
2012-01-02 00:00:00.000 A1 A1B2 14
2012-01-03 00:00:00.000 A1 A1B2 0
2012-01-01 00:00:00.000 A2 A2B2 0
2012-01-02 00:00:00.000 A2 A2B2 100
2012-01-03 00:00:00.000 A2 A2B2 0
答案 0 :(得分:1)
要使Value列包含值0而不是NULL,请使用:
SELECT Date, A, B, ISNULL(Value,0)
FROM
(
SELECT StartDate, A, B, Value
FROM Sample.dbo.Values
) X
RIGHT OUTER JOIN #CALENDAR
ON Date = StartDate
ORDER BY Date
同样,您可以使A和B列包含A1和B1,如下所示:
SELECT Date, ISNULL(A,'A1'), ISNULL(B,'B1'), ISNULL(Value,0)
FROM
(
SELECT StartDate, A, B, Value
FROM Sample.dbo.Values
) X
RIGHT OUTER JOIN #CALENDAR
ON Date = StartDate
ORDER BY Date
如果A和B还有其他值,这是否足够好从问题中不清楚。
答案 1 :(得分:1)
select
b.date,
a.A,
a.B,
case
when a.date = b.date then a.value
else 0
end as Value
from #temp a
cross join #calendar b
-- where b.date between -- as calendar filter
不是典型交叉连接的示例 我没有测试,但会在秒中进行:D