2011-03-04 83 views
1

我有这样SQL转换结果

输入DB数据

Id | Start Date | End Date | Value 
1  1/2/2010  1/6/2010  20 
2  1/5/2010  1/7/2010  80 

我需要使用SQL查询这样

OUTPUT改造这个数据

Id | Month  | Value 
1  1/2/2010  20 
1  1/3/2010  20 
1  1/4/2010  20 
1  1/5/2010  20 
1  1/6/2010  20 
2  1/5/2010  80 
2  1/6/2010  80 
2  1/7/2010  80 

请建议采取这种可能的解决方案。考虑到输入表具有数百万条记录的性能,我们需要处理所有记录。我正在使用SQL 2008,并希望避免循环或游标。谢谢。

回答

1

然后查看一下使用递归CTE查询。

喜欢的东西

DECLARE @Table TABLE(
    Id INT, 
    StartDate DATETIME, 
    EndDate DATETIME, 
    Value FLOAT 
) 

INSERT INTO @Table SELECT 1,'1/2/2010','1/6/2010',20 
INSERT INTO @Table SELECT 2,'1/5/2010','1/7/2010',80 

;WITH Vals AS (
     SELECT id, 
       StartDate, 
       EndDate, 
       Value 
     FROM @Table 
     UNION ALL 
     SELECT id, 
       StartDate + 1, 
       EndDate, 
       Value 
     FROM Vals 
     WHERE StartDate + 1 <= EndDate 
) 
SELECT * 
FROM Vals 
ORDER BY id, 
      StartDate 
OPTION (MAXRECURSION 0) 
+0

完美,但性能非常差。我有113000条记录,到目前为止,在半小时内它已经达到了11000条记录。我在CLR集成项目中有另一个解决方案,但它仍然更好(但不可接受)。性能是我寻找其他选项的主要关注点。 – hungryMind 2011-03-04 09:13:43

0

创建一个帮助台测试版:

CREATE TABLE Beta (
Monat DATETIME, 
) 

所有monthes填补它,你需要:

INSERT INTO Beta VALUES('1/1/2010') 
... 
INSERT INTO Beta VALUES('1/12/2010') ' maybe '12/1/2010' 

和:

SELECT A.Id, B.Monat, A.Value 
FROM <YourTable> A, Beta B 
WHERE B.Monat >= A.StartDate And B.Monat <= A.EndDate 

(无garanties WRT性能)

我没有牛逼预计这样的事情必须要“证明” -

=============================================================================== 
    SO5192555 - select for hungryMind 
    ------------------------------------------------------------------------------- 
    ------------------------------------------------------------------------------- 
    SELECT * FROM Alpha 
    ------------------------------------------------------------------------------- 
    |Id|StartDate|EndDate |Value| 
    | 1| 2/1/2010|6/1/2010| 20| 
    | 2| 5/1/2010|7/1/2010| 80| 
    ------------------------------------------------------------------------------- 
    ------------------------------------------------------------------------------- 
    SELECT A.Id, B.Monat, A.Value FROM Alpha A, Beta B WHERE B.Monat >= A.StartDate And B.Monat <= A.EndDate 
    ------------------------------------------------------------------------------- 
    |Id|Monat |Value| 
    | 1|2/1/2010| 20| 
    | 1|3/1/2010| 20| 
    | 1|4/1/2010| 20| 
    | 1|5/1/2010| 20| 
    | 1|6/1/2010| 20| 
    | 2|5/1/2010| 80| 
    | 2|6/1/2010| 80| 
    | 2|7/1/2010| 80| 
    =============================================================================== 
    xpladolib.vbs: Erfolgreich beendet. (0) [ 0.17969 secs ]  
+0

不,我的所有行都有不同的开始和结束日期。 – hungryMind 2011-03-04 14:46:53

+0

@hungryMind:se以上 – 2011-03-04 17:18:16

+0

我无法创建表测试版。我有几行(大约一百万),我将它们分组以获得最大和最小日期并插入到表beta中,并且在连接上执行查询,似乎不会给出更好的性能。 – hungryMind 2011-03-04 18:29:11

0

尽管hungryMind的“我不能”和“似乎”,我还是觉得用辅助 表是正确的路要走:

灌装台阿尔法器用50000分的记录,像

SELECT TOP 5 *, DATEDIFF("d", StartDate, EndDate) + 1 AS Days FROM Alpha ORDER BY Id 
------------------------------------------------------------------------------- 
|Id|StartDate |EndDate |Value|Days| 
| 1| 12/6/2001| 5/15/2002| 10| 161| 
| 2| 8/2/2001 |10/27/2001| 20| 87| 
| 3|10/28/2000| 6/17/2001| 30| 233| 
| 4| 1/15/2000| 8/30/2000| 40| 229| 
| 5| 3/25/2002|10/23/2002| 50| 213| 
------------------------------------------------------------------------------- 
SELECT TOP 5 *, DATEDIFF("d", StartDate, EndDate) + 1 AS Days FROM Alpha ORDER BY Id DESC 
------------------------------------------------------------------------------- 
|Id |StartDate |EndDate |Value |Days| 
|50000|10/31/2001| 5/6/2002 |500000| 188| 
|49999| 8/31/2002|12/31/2002|499990| 123| 
|49998| 4/11/2002|11/11/2002|499980| 215| 
|49997| 3/13/2002|12/16/2002|499970| 279| 
|49996| 7/4/2002 | 7/27/2002|499960| 24| 

,并基于MIN(起始日期)的范围内创建辅助表测试版... MAX(结束日期) - 我用一个循环来插入所有1297天 -

----------------------------------------------- 
SELECT TOP 5 * FROM Beta ORDER BY Monat 
----------------------------------------------- 
|Monat | 
|1/1/2000| 
|1/2/2000| 
|1/3/2000| 
|1/4/2000| 
|1/5/2000| 
----------------------------------------------- 
SELECT TOP 5 * FROM Beta ORDER BY Monat DESC 
----------------------------------------------- 
|Monat | 
|7/20/2003| 
|7/19/2003| 
|7/18/2003| 
|7/17/2003| 
|7/16/2003| 

和执行

SELECT A.Id, B.Monat, A.Value 
INTO Gamma FROM Alpha A, Beta B 
WHERE B.Monat >= A.StartDate And B.Monat <= A.E 

插入7.522.243记录到表伽玛:

SELECT TOP 5 * FROM Gamma Order BY Id, Monat 
----------------------------------------------------------- 
|Id|Monat  |Value| 
| 1| 12/6/2001| 10| <--- | 1| 12/6/2001| 5/15/2002| 10| 161| 
| 1| 12/7/2001| 10| 
| 1| 12/8/2001| 10| 
| 1| 12/9/2001| 10| 
| 1|12/10/2001| 10| 
----------------------------------------------------------- 
SELECT TOP 5 * FROM Gamma Order BY Id DESC, Monat 
----------------------------------------------------------- 
|Id |Monat  |Value | 
|50000|10/31/2001|500000| <---- |50000|10/31/2001| 5/6/2002 |500000| 188| 
|50000| 11/1/2001|500000| 
|50000| 11/2/2001|500000| 
|50000| 11/3/2001|500000| 
|50000| 11/4/2001|500000| 

拉着我的WinXP /的SQLExpress/1 GB/MEM VirtualBox虚拟机上约2分钟。做了 只是“SELECT INTO”花了26秒。

50.000源记录小于113000或“百万”,但我做了我的测试 通过VBScript中使用ADO/OLEDB。毫无疑问,MS Server Admin可以做得更好。

+0

我也会尝试这种方法。不管怎么说,还是要谢谢你。 – hungryMind 2011-03-05 09:17:36