【问题标题】:SQL Server : connect by level for DATE type with unionSQL Server:使用联合按级别连接 DATE 类型
【发布时间】:2014-01-08 04:13:47
【问题描述】:

我找到了替换 Oracle 的“CONNECT BY LEVEL”in this question 的基本答案,但我的情况有点复杂:

基本上我要替换的东西是这样的:

...
UNION ALL

Select 
    adate, 'ROAD' as TSERV_ID, 0 AS EQ_NBR
from 
   (SELECT 
        to_date(sysdate - 732,'dd/mm/yy') + rownum -1 as adate, rownum
    FROM 
        (select rownum 
         from dual 
         connect by level <= 732) 
    WHERE rownum <= 732)

UNION ALL

Select 
    adate, 'PORTPACK' as TSERV_ID, 0 AS EQ_NBR
from 
    (SELECT 
         to_date(sysdate - 732,'dd/mm/yy') + rownum -1 as adate, rownum
     FROM 
          (select rownum from dual connect by level <= 732) 
     WHERE rownum <= 732)

UNION ALL
....

现在,单双连接很容易,即使这显然不是很有效的方法

WITH CTE AS (
SELECT dateadd(day,-720,CONVERT (date, GETDATE())) as Datelist
UNION ALL
SELECT dateadd(day,1,Datelist)
FROM CTE 
WHERE datelist < getdate() )
SELECT *,'ROAD' as Tserv_ID , 0 as EQ_NBR FROM CTE
option (maxrecursion 0)

重复联合很难,因为我收到错误:

关键字“with”附近的语法不正确。如果这个语句是一个公用表表达式、一个 xmlnamespaces 子句或一个更改跟踪上下文子句,则前面的语句必须以分号结束。

我在这里提供了这个联合的更多部分;我尝试仅在开始时使用“WITH”,但没有运气。我在这里遗漏了什么明显的东西吗?

编辑:当然有一个很大的问题,为什么我什至要尝试做这样的事情:就我个人而言,我不会,但在查询的另一端有一个巨大的水晶报表,每个月运行一次,它接受这种特定格式的数据。完整查询输出的结尾类似于

3 columns of data
3 Columns of data
...
Currentdate-732,"ROAD",0
Currentdate -731,"ROAD",0
...
Currentdate, "ROAD,"0"
Currentdate -732, "PORTPAK", 0
Currentdate -731, "PORTPAK", 0

等等

【问题讨论】:

  • OP 中的最后一条语句是正确的并且在此处有效 (sqlfiddle.com/#!6/d41d8/13594)。您收到语法错误的查询是什么?
  • 这是正确的,如果单独使用,我无法使用相同的 CTE 进行联合,即 WITH CTE (Select....) UNION ALL WITH CTE (SELECT) U
  • SQL Server 2005 中引入的递归查询。您使用的是哪个版本?
  • @Kris 那是因为您的语法错误。在我的回答中,我向您展示了如何组合多个 CTE(以及更合理的方法)。现在不准确,因为您无法在上面的 720 天和 732 天之间做出决定,而且您的原始查询还包括明天(所以我的也是如此),但它应该让您非常接近。

标签: sql sql-server oracle


【解决方案1】:

你想做什么:

WITH CTE1 AS (...),
     CTE2 AS (...)
SELECT stuff FROM CTE1 
UNION ALL
SELECT stuff FROM CTE2;

?这是一个常见的挑战,我想为了使用多个 CTE,您只需用逗号分隔它们并不是很容易发现。

话虽如此,您似乎只是想生成一系列日期。递归 CTE(不要介意其中许多)不是最有效的方法。与其告诉我们您想要替换 CONNECT BY LEVEL 并向我们展示您尝试过的语法,不如直接展示或描述您想要的输出?我们已经感谢您自己尝试了一些东西(谢谢!),但我们宁愿为您提供一个有效的解决方案,而不是缩小与低效解决方案的差距。

例如,这里需要 很多 少冗余代码,并且 ( think 为您提供您所追求的:

DECLARE @n INT = 722, @d DATE = CURRENT_TIMESTAMP;

;WITH v AS (SELECT v FROM (VALUES('ROAD'),('PORTPACK')) AS v(v)),
      n AS (SELECT TOP (@n) n = ROW_NUMBER() OVER (ORDER BY number)
  FROM master.dbo.spt_values ORDER BY n)
SELECT Datelist = DATEADD(DAY, 2-n.n, @d), Tserv_ID = v.v, EQ_NBR = 0
FROM n CROSS JOIN v
ORDER BY Tserv_ID, Datelist;

【讨论】:

  • 我想要的输出和原始查询的输出是 DATE-732,"ROAD",0; DATE-731,"ROAD",0....DATE-732,"PORTPAK",0; DATE-731,"PORTPACK",0 等。我只是想遵循一些糟糕的书面代码,因为在另一端是相当复杂的水晶报告,它的格式可以完全接受这种格式。
  • 谢谢,现在可以使用了。在这个阶段我不关心效率。值得一提的是 OPTION (maxrecurse 0) 在这里是一个问题 - 必须放在查询的底部,或者(如果查询保存为视图)完全省略,然后使用 OPTION (SELECT * FROM My_Query_as_a_view OPTION (Maxrecurse 0). MS SQL 2008 R2 的乐趣:/
  • @Kris 我完全不明白为什么你需要在这里使用递归 CTE。后一个示例不是我提供了一种更具可扩展性和可读性的方法吗?
  • 你的第二种方法更容易,但是AFAIK你不能用DECLARE创建视图
  • 也简单地说 CRYSTAL 不想接受它,即使是命令 :( 所以换句话说我必须坚持 CTE
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-27
  • 1970-01-01
  • 1970-01-01
  • 2023-03-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多