在 SQL Server 2008 中的通用 Table 表达式中使用分组依据
Using group by in Common Table Expression in SQL Server 2008
我正在尝试对不同行数据进行平均,如下所示。
所以基本上这里是 table
create table t (id int identity, BIDID int, AppID int, AppStatus varchar(20), [Time] date);
insert into t values
(23390, 16, 'In Review', '20170307'),
(23390, 16, 'Approved', '20170309'),
(23390, 16, 'In Review', '20171110'),
(23390, 16, 'Approved', '20171112'),
(23390, 17, 'In Review', '20171114'),
(23390, 18, 'Approved', '20171112'),
(23390, 16, 'Approved', '20171114'),
(23391, 17, 'In Review', '20171112'),
(23391, 17, 'Approved', '20171114')
我试图首先在单个 AppID 之间计算审查中值和批准值之间的平均值,然后在单个出价中计算不同 AppId 的平均值,最后在所有出价之间计算平均值以得出单号
这是它的代码
SELECT
CASE WHEN t1.AppStatus = 'In Review' AND t2.AppStatus = 'Approved'
THEN DATEDIFF(day, t1.[Time], t2.[Time])
ELSE 0
END as Days
FROM
t t1
CROSS APPLY(SELECT TOP 1 *
FROM t
WHERE id > t1.id
ORDER BY id) t2
这让我得到了平均值
WITH ct AS
(
SELECT
CASE WHEN t1.AppStatus = 'In Review' AND t2.AppStatus = 'Approved'
THEN DATEDIFF(day, t1.[Time], t2.[Time])
ELSE 0
END as Days
FROM
t t1
CROSS APPLY(SELECT TOP 1 *
FROM t
WHERE id > t1.id
ORDER BY id) t2
)
SELECT
SUM(days) / COUNT(*) Average
FROM
ct
WHERE
days <> 0
这目前不进行任何类型的分组,所以它只是首先考虑 In Review,然后找到下一个 Approved 等等。我需要先按 AppID 对其进行分组以计算单个 AppId 的平均值,然后对出价内的不同 AppId 求平均值,然后对出价的
求平均值
谁能告诉我应该如何添加分组。
预期结果
(1 23390, 16, 'In Review', '20170308'),
(2 23390, 16, 'Approved', '20170309'),
(3 23390, 16, 'In Review', '20171110'),
(4 23390, 16, 'Approved', '20171112'),
(5 23390, 17, 'In Review', '20171114'),
(6 23390, 18, 'In Review', '20171112'),
(7 23390, 16, 'Approved', '20171114'),
(8 23391, 17, 'In Review', '20171112'),
(9 23391, 17, 'Approved', '20171114')
23390 AppID16 FirstData Id1 to Id2 1Day (In Review -> Approved)
23390 AppID16 SecondData Id3 to Id4 2Day
23390 AppID16 ThirdData Id7 Ignored Since no In Review Before..
Avg AppID 16 = 1.5 days
23390 AppID 17 ignored since no Approved after in review
23390 AppID 18 Ignored
Avg for 23390 = 1.5
..类似地计算其他出价的平均值
23391 AppID 17 天 2.
所以出价之间的总平均数是 2 + 1.5 / 2
谢谢
这是一种方法。非常简单。每个步骤都包含在 CTE 中。检查每个 CTE 的中间结果以了解其工作原理并查看代码中的注释。
示例数据
create table t (id int identity, BIDID int, AppID int, AppStatus varchar(20), dt date);
insert into t values
(23390, 16, 'In Review', '20170308'),
(23390, 16, 'Approved', '20170309'),
(23390, 16, 'In Review', '20171110'),
(23390, 16, 'Approved', '20171112'),
(23390, 17, 'In Review', '20171114'),
(23390, 18, 'Approved', '20171112'),
(23390, 16, 'Approved', '20171114'),
(23391, 17, 'In Review', '20171112'),
(23391, 17, 'Approved', '20171114');
查询
我调整了你的CROSS APPLY
以匹配你在问题中描述的逻辑。
WITH
-- Find matching pairs and calculate the difference of individual dates
CTE_Diffs
AS
(
SELECT
MainT.id
,MainT.BIDID
,MainT.AppID
,CAST(DATEDIFF(day, MainT.dt, NextT.dt) AS float) AS Diff
FROM
T AS MainT
CROSS APPLY
(
SELECT TOP 1
T.AppStatus
,T.dt
FROM T
WHERE
-- the matching row must be from the same Bid and App
-- and have a higher ID
T.BIDID = MainT.BIDID
AND T.AppID = MainT.AppID
AND T.id > MainT.id
ORDER BY
T.id
) AS NextT
WHERE
-- the pair is counted only when it starts with 'In Review' and finishes with 'Approved'
MainT.AppStatus = 'In Review'
AND NextT.AppStatus = 'Approved'
)
-- Average by Bid and App
,CTE_AvgBidApp
AS
(
SELECT
BIDID
,AppID
,AVG(Diff) AS AvgBidApp
FROM CTE_Diffs
GROUP BY
BIDID
,AppID
)
-- Average by Bid
,CTE_AvgBid
AS
(
SELECT
BIDID
,AVG(AvgBidApp) AS AvgBid
FROM CTE_AvgBidApp
GROUP BY
BIDID
)
-- Final average
SELECT
AVG(AvgBid) AS TotalAvg
FROM CTE_AvgBid
;
结果
TotalAvg
1.75
清理
DROP TABLE t;
我正在尝试对不同行数据进行平均,如下所示。
所以基本上这里是 table
create table t (id int identity, BIDID int, AppID int, AppStatus varchar(20), [Time] date);
insert into t values
(23390, 16, 'In Review', '20170307'),
(23390, 16, 'Approved', '20170309'),
(23390, 16, 'In Review', '20171110'),
(23390, 16, 'Approved', '20171112'),
(23390, 17, 'In Review', '20171114'),
(23390, 18, 'Approved', '20171112'),
(23390, 16, 'Approved', '20171114'),
(23391, 17, 'In Review', '20171112'),
(23391, 17, 'Approved', '20171114')
我试图首先在单个 AppID 之间计算审查中值和批准值之间的平均值,然后在单个出价中计算不同 AppId 的平均值,最后在所有出价之间计算平均值以得出单号
这是它的代码
SELECT
CASE WHEN t1.AppStatus = 'In Review' AND t2.AppStatus = 'Approved'
THEN DATEDIFF(day, t1.[Time], t2.[Time])
ELSE 0
END as Days
FROM
t t1
CROSS APPLY(SELECT TOP 1 *
FROM t
WHERE id > t1.id
ORDER BY id) t2
这让我得到了平均值
WITH ct AS
(
SELECT
CASE WHEN t1.AppStatus = 'In Review' AND t2.AppStatus = 'Approved'
THEN DATEDIFF(day, t1.[Time], t2.[Time])
ELSE 0
END as Days
FROM
t t1
CROSS APPLY(SELECT TOP 1 *
FROM t
WHERE id > t1.id
ORDER BY id) t2
)
SELECT
SUM(days) / COUNT(*) Average
FROM
ct
WHERE
days <> 0
这目前不进行任何类型的分组,所以它只是首先考虑 In Review,然后找到下一个 Approved 等等。我需要先按 AppID 对其进行分组以计算单个 AppId 的平均值,然后对出价内的不同 AppId 求平均值,然后对出价的
求平均值谁能告诉我应该如何添加分组。
预期结果
(1 23390, 16, 'In Review', '20170308'),
(2 23390, 16, 'Approved', '20170309'),
(3 23390, 16, 'In Review', '20171110'),
(4 23390, 16, 'Approved', '20171112'),
(5 23390, 17, 'In Review', '20171114'),
(6 23390, 18, 'In Review', '20171112'),
(7 23390, 16, 'Approved', '20171114'),
(8 23391, 17, 'In Review', '20171112'),
(9 23391, 17, 'Approved', '20171114')
23390 AppID16 FirstData Id1 to Id2 1Day (In Review -> Approved)
23390 AppID16 SecondData Id3 to Id4 2Day
23390 AppID16 ThirdData Id7 Ignored Since no In Review Before..
Avg AppID 16 = 1.5 days
23390 AppID 17 ignored since no Approved after in review
23390 AppID 18 Ignored
Avg for 23390 = 1.5
..类似地计算其他出价的平均值
23391 AppID 17 天 2.
所以出价之间的总平均数是 2 + 1.5 / 2
谢谢
这是一种方法。非常简单。每个步骤都包含在 CTE 中。检查每个 CTE 的中间结果以了解其工作原理并查看代码中的注释。
示例数据
create table t (id int identity, BIDID int, AppID int, AppStatus varchar(20), dt date);
insert into t values
(23390, 16, 'In Review', '20170308'),
(23390, 16, 'Approved', '20170309'),
(23390, 16, 'In Review', '20171110'),
(23390, 16, 'Approved', '20171112'),
(23390, 17, 'In Review', '20171114'),
(23390, 18, 'Approved', '20171112'),
(23390, 16, 'Approved', '20171114'),
(23391, 17, 'In Review', '20171112'),
(23391, 17, 'Approved', '20171114');
查询
我调整了你的CROSS APPLY
以匹配你在问题中描述的逻辑。
WITH
-- Find matching pairs and calculate the difference of individual dates
CTE_Diffs
AS
(
SELECT
MainT.id
,MainT.BIDID
,MainT.AppID
,CAST(DATEDIFF(day, MainT.dt, NextT.dt) AS float) AS Diff
FROM
T AS MainT
CROSS APPLY
(
SELECT TOP 1
T.AppStatus
,T.dt
FROM T
WHERE
-- the matching row must be from the same Bid and App
-- and have a higher ID
T.BIDID = MainT.BIDID
AND T.AppID = MainT.AppID
AND T.id > MainT.id
ORDER BY
T.id
) AS NextT
WHERE
-- the pair is counted only when it starts with 'In Review' and finishes with 'Approved'
MainT.AppStatus = 'In Review'
AND NextT.AppStatus = 'Approved'
)
-- Average by Bid and App
,CTE_AvgBidApp
AS
(
SELECT
BIDID
,AppID
,AVG(Diff) AS AvgBidApp
FROM CTE_Diffs
GROUP BY
BIDID
,AppID
)
-- Average by Bid
,CTE_AvgBid
AS
(
SELECT
BIDID
,AVG(AvgBidApp) AS AvgBid
FROM CTE_AvgBidApp
GROUP BY
BIDID
)
-- Final average
SELECT
AVG(AvgBid) AS TotalAvg
FROM CTE_AvgBid
;
结果
TotalAvg
1.75
清理
DROP TABLE t;