使用 CTE 将多个结果集合并为一个具有单独列的结果集
Using CTE to union multiple result sets into one result set with separate columns
我正在尝试使用 CTE 将多个结果集合并为一个包含 6 列的结果集。
这是我开始的查询,它return有 3 个结果集,每个结果集有 2 行:
DECLARE @User AS VARCHAR(50)
SET @User = 'testuser'
DECLARE @LastYearEndDate AS DATETIME
DECLARE @LastMonthEndDate AS DATETIME
DECLARE @LastWeekEndDate AS DATETIME
SET @LastYearEndDate = (SELECT DATEADD(dd,-1, DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0)))
SET @LastMonthEndDate = (SELECT DATEADD(d,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0)))
SET @LastWeekEndDate = (SELECT DATEADD(day, -1 - (DATEPART(dw, GETDATE()) + @@DATEFIRST - 2) % 7, GETDATE()))
SELECT SUM(os.db_Exp)
AS YearToDateRevenue,
COUNT(*) AS YearToDateCount
FROM tblOrderSum os
JOIN tblUserProfile up
ON os.db_RTS = up.db_UserId
WHERE os.db_Deleted = 0
AND os.db_Date39 > @LastYearEndDate
AND os.db_Date45 = '1900/01/01'
AND db_Email LIKE @User + '%'
SELECT SUM(os.db_Exp)
AS MonthToDateRevenue,
COUNT(*) AS MonthToDateCount
FROM tblOrderSum os
JOIN tblUserProfile up
ON os.db_RTS = up.db_UserId
WHERE os.db_Deleted = 0
AND os.db_Date39 > @LastMonthEndDate
AND os.db_Date45 = '1900/01/01'
AND db_Email LIKE @User + '%'
SELECT SUM(os.db_Exp)
AS WeekToDateRevenue,
COUNT(*) AS WeekToDateCount
FROM tblOrderSum os
JOIN tblUserProfile up
ON os.db_RTS = up.db_UserId
WHERE os.db_Deleted = 0
AND os.db_Date39 > @LastWeekEndDate
AND os.db_Date45 = '1900/01/01'
AND db_Email LIKE @User + '%'
输出:
Result set 1:
YearToDateRevenue | YearToDateCount
120 3
Result set 2:
MonthToDateRevenue | MonthToDateCount
75 2
Result set 3:
WeekToDateRevenue | WeekToDateCount
18 1
也许有一种更简单的方法可以做到这一点,因为我每次只切换一个参数,但这是我的尝试:
/* Same declarations as above */
WITH cte AS (
SELECT
os.db_Exp
FROM tblOrderSum os
JOIN tblUserProfile up
ON os.db_RTS = up.db_UserId
WHERE os.db_Deleted = 0
AND os.db_Date39 > @LastYearEndDate
AND os.db_Date39 > @LastMonthEndDate
AND os.db_Date39 > @LastWeekEndDate
AND os.db_Date45 = '1900/01/01'
AND db_Email LIKE @User + '%')
SELECT
(SELECT SUM(os.db_Exp) AS YearToDateRevenue,
COUNT(*) AS YearToDateCount
FROM cte
WHERE os.db_Date39 > @LastYearEndDate)
(SELECT SUM(os.db_Exp) AS YearToDateRevenue,
COUNT(*) AS YearToDateCount
FROM cte
WHERE os.db_Date39 > @LastMonthEndDate)
(SELECT SUM(os.db_Exp) AS YearToDateRevenue,
COUNT(*) AS YearToDateCount
FROM cte
WHERE os.db_Date39 > @LastWeekEndDate)
现在我收到错误:
Msg 4104, Level 16, State 1, Line 28
The multi-part identifier "os.db_Date39" could not be bound.
Msg 4104, Level 16, State 1, Line 25
The multi-part identifier "os.db_Exp" could not be bound.
Msg 116, Level 16, State 1, Line 30
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.
我试图获得的输出:
YearToDateRevenue | YearToDateCount | MonthToDateRevenue | MonthToDateCount | WeekToDateRevenue | WeekToDateCount
120 3 75 2 18 1
我不确定将参数合并到 cte 并将其发送到 运行 的正确方法。任何我没有看到的更简单的解决方案也将不胜感激。我只是希望将每个总和计算在不同的列中。每个数字只有一个 returned,所以这应该 return 一行和 6 列。谢谢
有几种不同的方法可以解决这个问题,但我相信最快的方法是使用类似这样的东西......这是对你的第一个查询的修改,应该让你起来并运行 很快。有更好的方法可以做到这一点,但根据您的问题和提供的信息,这会让您振作起来 运行。
DECLARE @User AS VARCHAR(50)
SET @User = 'testuser'
DECLARE @LastYearEndDate AS DATETIME
DECLARE @LastMonthEndDate AS DATETIME
DECLARE @LastWeekEndDate AS DATETIME
SET @LastYearEndDate = (SELECT DATEADD(dd,-1, DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0)))
SET @LastMonthEndDate = (SELECT DATEADD(d,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0)))
SET @LastWeekEndDate = (SELECT DATEADD(day, -1 - (DATEPART(dw, GETDATE()) + @@DATEFIRST - 2) % 7, GETDATE()))
with YTD_total as (
SELECT 1 as joinpoint
SUM(os.db_Exp)
AS YearToDateRevenue,
COUNT(*) AS YearToDateCount
FROM tblOrderSum os
JOIN tblUserProfile up
ON os.db_RTS = up.db_UserId
WHERE os.db_Deleted = 0
AND os.db_Date39 > @LastYearEndDate
AND os.db_Date45 = '1900/01/01'
AND db_Email LIKE @User + '%'
),
MTD_total as (
SELECT 1 as joinpoint
SUM(os.db_Exp)
AS MonthToDateRevenue,
COUNT(*) AS MonthToDateCount
FROM tblOrderSum os
JOIN tblUserProfile up
ON os.db_RTS = up.db_UserId
WHERE os.db_Deleted = 0
AND os.db_Date39 > @LastMonthEndDate
AND os.db_Date45 = '1900/01/01'
AND db_Email LIKE @User + '%'
),
WTD_total as (
SELECT 1 as joinpoint
SUM(os.db_Exp)
AS WeekToDateRevenue,
COUNT(*) AS WeekToDateCount
FROM tblOrderSum os
JOIN tblUserProfile up
ON os.db_RTS = up.db_UserId
WHERE os.db_Deleted = 0
AND os.db_Date39 > @LastWeekEndDate
AND os.db_Date45 = '1900/01/01'
AND db_Email LIKE @User + '%'
)
select YearToDateRevenue,
YearToDateCount,
MonthToDateRevenue,
MonthToDateCount
WeekToDateRevenue,
WeekToDateCount
from ytd_totals ytd
join mtd_total mtd
on mtd.joinpoint = ytd.joinpoint
join wtd_total wtd
on wtd.joinpoint = mtd.joinpoint
您可以使用 CASE
来实现:
SELECT SUM(CASE WHEN os.db_Date39 > @LastYearEndDate THEN os.db_Exp ELSE 0 END) AS YearToDateRevenue,
SUM(CASE WHEN os.db_Date39 > @LastYearEndDate THEN 1 ELSE 0 END) AS YearToDateCount,
SUM(CASE WHEN os.db_Date39 > @LastMonthEndDate THEN os.db_Exp ELSE 0 END) AS MonthToDateRevenue,
SUM(CASE WHEN os.db_Date39 > @LastMonthEndDate THEN 1 ELSE 0 END) AS MonthToDateCount,
SUM(CASE WHEN os.db_Date39 > @LastWeekEndDate THEN os.db_Exp ELSE 0 END) AS WeekToDateRevenue,
SUM(CASE WHEN os.db_Date39 > @LastWeekEndDate THEN 1 ELSE 0 END) AS WeekToDateCount
FROM tblOrderSum os
JOIN tblUserProfile up
ON os.db_RTS = up.db_UserId
WHERE os.db_Deleted = 0
AND os.db_Date45 = '1900/01/01'
AND db_Email LIKE @User + '%'
我正在尝试使用 CTE 将多个结果集合并为一个包含 6 列的结果集。
这是我开始的查询,它return有 3 个结果集,每个结果集有 2 行:
DECLARE @User AS VARCHAR(50)
SET @User = 'testuser'
DECLARE @LastYearEndDate AS DATETIME
DECLARE @LastMonthEndDate AS DATETIME
DECLARE @LastWeekEndDate AS DATETIME
SET @LastYearEndDate = (SELECT DATEADD(dd,-1, DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0)))
SET @LastMonthEndDate = (SELECT DATEADD(d,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0)))
SET @LastWeekEndDate = (SELECT DATEADD(day, -1 - (DATEPART(dw, GETDATE()) + @@DATEFIRST - 2) % 7, GETDATE()))
SELECT SUM(os.db_Exp)
AS YearToDateRevenue,
COUNT(*) AS YearToDateCount
FROM tblOrderSum os
JOIN tblUserProfile up
ON os.db_RTS = up.db_UserId
WHERE os.db_Deleted = 0
AND os.db_Date39 > @LastYearEndDate
AND os.db_Date45 = '1900/01/01'
AND db_Email LIKE @User + '%'
SELECT SUM(os.db_Exp)
AS MonthToDateRevenue,
COUNT(*) AS MonthToDateCount
FROM tblOrderSum os
JOIN tblUserProfile up
ON os.db_RTS = up.db_UserId
WHERE os.db_Deleted = 0
AND os.db_Date39 > @LastMonthEndDate
AND os.db_Date45 = '1900/01/01'
AND db_Email LIKE @User + '%'
SELECT SUM(os.db_Exp)
AS WeekToDateRevenue,
COUNT(*) AS WeekToDateCount
FROM tblOrderSum os
JOIN tblUserProfile up
ON os.db_RTS = up.db_UserId
WHERE os.db_Deleted = 0
AND os.db_Date39 > @LastWeekEndDate
AND os.db_Date45 = '1900/01/01'
AND db_Email LIKE @User + '%'
输出:
Result set 1:
YearToDateRevenue | YearToDateCount
120 3
Result set 2:
MonthToDateRevenue | MonthToDateCount
75 2
Result set 3:
WeekToDateRevenue | WeekToDateCount
18 1
也许有一种更简单的方法可以做到这一点,因为我每次只切换一个参数,但这是我的尝试:
/* Same declarations as above */
WITH cte AS (
SELECT
os.db_Exp
FROM tblOrderSum os
JOIN tblUserProfile up
ON os.db_RTS = up.db_UserId
WHERE os.db_Deleted = 0
AND os.db_Date39 > @LastYearEndDate
AND os.db_Date39 > @LastMonthEndDate
AND os.db_Date39 > @LastWeekEndDate
AND os.db_Date45 = '1900/01/01'
AND db_Email LIKE @User + '%')
SELECT
(SELECT SUM(os.db_Exp) AS YearToDateRevenue,
COUNT(*) AS YearToDateCount
FROM cte
WHERE os.db_Date39 > @LastYearEndDate)
(SELECT SUM(os.db_Exp) AS YearToDateRevenue,
COUNT(*) AS YearToDateCount
FROM cte
WHERE os.db_Date39 > @LastMonthEndDate)
(SELECT SUM(os.db_Exp) AS YearToDateRevenue,
COUNT(*) AS YearToDateCount
FROM cte
WHERE os.db_Date39 > @LastWeekEndDate)
现在我收到错误:
Msg 4104, Level 16, State 1, Line 28
The multi-part identifier "os.db_Date39" could not be bound.
Msg 4104, Level 16, State 1, Line 25
The multi-part identifier "os.db_Exp" could not be bound.
Msg 116, Level 16, State 1, Line 30
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.
我试图获得的输出:
YearToDateRevenue | YearToDateCount | MonthToDateRevenue | MonthToDateCount | WeekToDateRevenue | WeekToDateCount
120 3 75 2 18 1
我不确定将参数合并到 cte 并将其发送到 运行 的正确方法。任何我没有看到的更简单的解决方案也将不胜感激。我只是希望将每个总和计算在不同的列中。每个数字只有一个 returned,所以这应该 return 一行和 6 列。谢谢
有几种不同的方法可以解决这个问题,但我相信最快的方法是使用类似这样的东西......这是对你的第一个查询的修改,应该让你起来并运行 很快。有更好的方法可以做到这一点,但根据您的问题和提供的信息,这会让您振作起来 运行。
DECLARE @User AS VARCHAR(50)
SET @User = 'testuser'
DECLARE @LastYearEndDate AS DATETIME
DECLARE @LastMonthEndDate AS DATETIME
DECLARE @LastWeekEndDate AS DATETIME
SET @LastYearEndDate = (SELECT DATEADD(dd,-1, DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0)))
SET @LastMonthEndDate = (SELECT DATEADD(d,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0)))
SET @LastWeekEndDate = (SELECT DATEADD(day, -1 - (DATEPART(dw, GETDATE()) + @@DATEFIRST - 2) % 7, GETDATE()))
with YTD_total as (
SELECT 1 as joinpoint
SUM(os.db_Exp)
AS YearToDateRevenue,
COUNT(*) AS YearToDateCount
FROM tblOrderSum os
JOIN tblUserProfile up
ON os.db_RTS = up.db_UserId
WHERE os.db_Deleted = 0
AND os.db_Date39 > @LastYearEndDate
AND os.db_Date45 = '1900/01/01'
AND db_Email LIKE @User + '%'
),
MTD_total as (
SELECT 1 as joinpoint
SUM(os.db_Exp)
AS MonthToDateRevenue,
COUNT(*) AS MonthToDateCount
FROM tblOrderSum os
JOIN tblUserProfile up
ON os.db_RTS = up.db_UserId
WHERE os.db_Deleted = 0
AND os.db_Date39 > @LastMonthEndDate
AND os.db_Date45 = '1900/01/01'
AND db_Email LIKE @User + '%'
),
WTD_total as (
SELECT 1 as joinpoint
SUM(os.db_Exp)
AS WeekToDateRevenue,
COUNT(*) AS WeekToDateCount
FROM tblOrderSum os
JOIN tblUserProfile up
ON os.db_RTS = up.db_UserId
WHERE os.db_Deleted = 0
AND os.db_Date39 > @LastWeekEndDate
AND os.db_Date45 = '1900/01/01'
AND db_Email LIKE @User + '%'
)
select YearToDateRevenue,
YearToDateCount,
MonthToDateRevenue,
MonthToDateCount
WeekToDateRevenue,
WeekToDateCount
from ytd_totals ytd
join mtd_total mtd
on mtd.joinpoint = ytd.joinpoint
join wtd_total wtd
on wtd.joinpoint = mtd.joinpoint
您可以使用 CASE
来实现:
SELECT SUM(CASE WHEN os.db_Date39 > @LastYearEndDate THEN os.db_Exp ELSE 0 END) AS YearToDateRevenue,
SUM(CASE WHEN os.db_Date39 > @LastYearEndDate THEN 1 ELSE 0 END) AS YearToDateCount,
SUM(CASE WHEN os.db_Date39 > @LastMonthEndDate THEN os.db_Exp ELSE 0 END) AS MonthToDateRevenue,
SUM(CASE WHEN os.db_Date39 > @LastMonthEndDate THEN 1 ELSE 0 END) AS MonthToDateCount,
SUM(CASE WHEN os.db_Date39 > @LastWeekEndDate THEN os.db_Exp ELSE 0 END) AS WeekToDateRevenue,
SUM(CASE WHEN os.db_Date39 > @LastWeekEndDate THEN 1 ELSE 0 END) AS WeekToDateCount
FROM tblOrderSum os
JOIN tblUserProfile up
ON os.db_RTS = up.db_UserId
WHERE os.db_Deleted = 0
AND os.db_Date45 = '1900/01/01'
AND db_Email LIKE @User + '%'