[英]How to use WITH clause with UNION ALL in SQL Server
我正在尝试,但我不知道如何将两个 SQL 语句(包括WITH
子句)与UNION ALL
结合起来。 在每个WITH
SQL 语句中,不同之处在于WHERE
子句。
WITH cte AS
(
SELECT
CMCONTRACTS.CMSERIALNUMBER, CMACTIVITIES.CMID,
CMACTIVITIES.CMSTART, CMACTIVITIES.CMFINISH,
CMACTIVITIES.CMSTATUSTYPE,
ROW_NUMBER() OVER (PARTITION BY CMCONTRACTS.CMSERIALNUMBER
ORDER BY CMACTIVITIES.CMFINISH DESC) RN
FROM
CMACTIVITIES
LEFT JOIN
CMCONTRACTS ON CMACTIVITIES.CMCONTRACTID = CMCONTRACTS.CMID
WHERE
CMACTIVITIES.CMSTATUSTYPE = 3
)
SELECT
CMID, CMSTART, CMFINISH, CMSERIALNUMBER, CMSTATUSTYPE
FROM
cte
WHERE
RN = 1
UNION ALL
WITH cte AS
(
SELECT
CMCONTRACTS.CMSERIALNUMBER, CMACTIVITIES.CMID,
CMACTIVITIES.CMSTART, CMACTIVITIES.CMFINISH,
CMACTIVITIES.CMSTATUSTYPE,
ROW_NUMBER() OVER (PARTITION BY CMCONTRACTS.CMSERIALNUMBER
ORDER BY CMACTIVITIES.CMFINISH ASC) RN
FROM
CMACTIVITIES
LEFT JOIN
CMCONTRACTS ON CMACTIVITIES.CMCONTRACTID = CMCONTRACTS.CMID
WHERE
CMACTIVITIES.CMSTATUSTYPE = '2'
)
SELECT
CMID, CMSTART, CMFINISH, CMSERIALNUMBER, CMSTATUSTYPE
-- GXSTARTDATE, GXENDDATE, GXFORMULA, GXPRLSID
FROM
cte
WHERE
RN = 1
当我运行它时,出现以下错误:
消息 156,15 级,State 1,第 26 行
关键字“WITH”附近的语法不正确。消息 319,15 级,State 1,第 26 行
关键字“with”附近的语法不正确。 如果此语句是公用表表达式、xmlnamespaces 子句或更改跟踪上下文子句,则前一个语句必须以分号结尾。
运行这两个单独的 SQL 查询会得到预期的结果。 但是我想从之前的两个 SQL 查询中获取所有结果,包括一个查询中的WITH
子句。
你应该首先像这样制作 CTE:
WITH cte
AS (SELECT
CMCONTRACTS.CMSERIALNUMBER,
CMACTIVITIES.CMID,
CMACTIVITIES.CMSTART,
CMACTIVITIES.CMFINISH,
CMACTIVITIES.CMSTATUSTYPE,
ROW_NUMBER() OVER (PARTITION BY CMCONTRACTS.CMSERIALNUMBER
ORDER BY CMACTIVITIES.CMFINISH DESC
) RN
FROM CMACTIVITIES
LEFT JOIN CMCONTRACTS ON CMACTIVITIES.CMCONTRACTID = CMCONTRACTS.CMID
WHERE CMACTIVITIES.CMSTATUSTYPE = 3),
cte2
AS (SELECT
CMCONTRACTS.CMSERIALNUMBER,
CMACTIVITIES.CMID,
CMACTIVITIES.CMSTART,
CMACTIVITIES.CMFINISH,
CMACTIVITIES.CMSTATUSTYPE,
ROW_NUMBER() OVER (PARTITION BY CMCONTRACTS.CMSERIALNUMBER
ORDER BY CMACTIVITIES.CMFINISH ASC
) RN
FROM CMACTIVITIES
LEFT JOIN CMCONTRACTS ON CMACTIVITIES.CMCONTRACTID = CMCONTRACTS.CMID
WHERE CMACTIVITIES.CMSTATUSTYPE = '2')
SELECT
CMID,
CMSTART,
CMFINISH,
CMSERIALNUMBER,
CMSTATUSTYPE
FROM cte
WHERE RN = 1
UNION ALL
SELECT
CMID,
CMSTART,
CMFINISH,
CMSERIALNUMBER,
CMSTATUSTYPE -- GXSTARTDATE, GXENDDATE, GXFORMULA, GXPRLSID
FROM cte2
WHERE RN = 1;
在此特定实例中,您不需要两个 CTE,只需将CMACTIVITIES.CMSTATUSTYPE
添加到PARTITION BY
子句即可。
WITH cte AS (
SELECT
c.CMSERIALNUMBER,
a.CMID,
a.CMSTART,
a.CMFINISH,
a.CMSTATUSTYPE,
ROW_NUMBER() OVER (PARTITION BY c.CMSERIALNUMBER, a.CMSTATUSTYPE
ORDER BY
CASE WHEN a.CMSTATUSTYPE = 2 THEN a.CMFINISH END ASC,
CASE WHEN a.CMSTATUSTYPE = 3 THEN a.CMFINISH END DESC
) RN
FROM CMACTIVITIES a
LEFT JOIN CMCONTRACTS c ON a.CMCONTRACTID = c.CMID
WHERE a.CMSTATUSTYPE IN (2, 3)
)
SELECT
CMID,
CMSTART,
CMFINISH,
CMSERIALNUMBER,
CMSTATUSTYPE
FROM cte
WHERE RN = 1;
不清楚CMSTATUSTYPE
是字符串还是数字。 您应该坚持列被定义为的那个。
您接受的答案不是很干。
除了在不同的CMSTATUSTYPE
上过滤和行编号的不同排序方向外,CTE 的两个分支几乎完全相同。
您无需使用LAG
和LEAD
在两个方向上进行排序即可有效地获得此结果。
在下面,所有行的IsStartOfGroup
和IsEndOfGroup
值都将具有0
,除非没有上一行或下一行(分别),在这种情况下,该标志将设置为1
。
WITH CTE AS
(
SELECT CMCONTRACTS.CMSERIALNUMBER,
CMACTIVITIES.CMID,
CMACTIVITIES.CMSTART,
CMACTIVITIES.CMFINISH,
CMACTIVITIES.CMSTATUSTYPE,
LAG(0,1,1) OVER (PARTITION BY CMCONTRACTS.CMSERIALNUMBER ORDER BY CMACTIVITIES.CMFINISH ASC) AS IsStartOfGroup,
LEAD(0,1,1) OVER (PARTITION BY CMCONTRACTS.CMSERIALNUMBER ORDER BY CMACTIVITIES.CMFINISH ASC) AS IsEndOfGroup
FROM CMACTIVITIES
LEFT JOIN CMCONTRACTS
ON CMACTIVITIES.CMCONTRACTID = CMCONTRACTS.CMID
WHERE CMACTIVITIES.CMSTATUSTYPE IN (2,3)
)
SELECT *
FROM CTE
WHERE (CMSTATUSTYPE = 2 AND IsStartOfGroup = 1)
OR (CMSTATUSTYPE = 3 AND IsEndOfGroup = 1)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.