0

我有一个表,我想加入一个日历表来生成一个时间序列,我这样做是这样的:

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 的列包含NULLs 即我得到这样的东西:

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
4

2 回答 2

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 有其他值,这是否足够好从问题中不清楚。

于 2013-01-18T09:09:50.327 回答
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

这不是我没有测试过的典型交叉连接的例子,但会在 sec 中进行:D

于 2013-01-18T09:20:35.177 回答