将丑陋的 T SQL 查询转换为 CTE
Convert ugly T SQL query to CTE
我在将 TSQL 查询转换为 cte 时遇到问题。我很确定这是一个候选人。我在其他查询中使用过 cte,但这个查询必须从多个来源获取数据,这让我有些伤心。这是我得到的有效方法:
declare @projid int = 0
declare @proj varchar = (select projectid from Projects where projectid = @projid)
declare @maxid int = (select max(projectid) from Projects)
declare @projsize bigint = (select projectsizeexpitem from Projects where projectid = @projid)
declare @numofdays int = (select DATEDIFF(DAY, MIN(starttime), GETDATE()) from transactions where projectid = @projid)
declare @dailyrate bigint = (select (SUM(transactionitemsmigrated)/@numofdays) from Transactions where projectid = @projid)
declare @complete bigint = (select SUM(transactionitemsmigrated) from transactions where projectid = @projid)
declare @daysremaining int = (select (CAST(GETDATE() AS int) + ((@projsize-@complete)/@dailyrate)))
WHILE @projid < @maxid
BEGIN
IF @projid IN (select projectid from projects)
BEGIN
set @proj = (select projectname from Projects where projectid = @projid)
set @maxid = (select max(projectid) from Projects)
set @projsize = (select projectsizeexpitem from Projects where projectid = @projid)
set @numofdays = (select DATEDIFF(DAY, MIN(starttime), GETDATE()) from transactions where projectid = @projid)
set @dailyrate = (select (SUM(transactionitemsmigrated)/@numofdays) from Transactions where projectid = @projid)
set @complete = (select SUM(transactionitemsmigrated) from transactions where projectid = @projid)
set @daysremaining = (select (CAST(GETDATE() AS int) + ((@projsize-@complete)/@dailyrate)))
select
[Project] = (select projectname from projects where projectid = @projid),
[TotalItems] = @projsize,
[DaysActive] = @numofdays,
[DailyRate] = @dailyrate,
[TotalComplete] = @complete,
[ItemsRemaining] = @projsize - @complete,
[DaysRemaining] = ((@projsize-@complete)/@dailyrate),
[CompDate] = CAST(CAST(@daysremaining AS datetime) AS date)
SET @projid = @projid + 1
END
ELSE
BEGIN
SET @projid = @projid + 1
END
END
这个问题是 returns SELECT 语句的每次迭代作为单独的结果 table。我想把它们放在一起进行聚合。这是我尝试过的:
declare @projid int = 0
declare @proj varchar = (select projectid from Projects where projectid = @projid)
declare @maxid int = (select max(projectid) from Projects)
declare @projsize bigint = (select projectsizeexpitem from Projects where projectid = @projid)
declare @numofdays int = (select DATEDIFF(DAY, MIN(starttime), GETDATE()) from transactions where projectid = @projid)
declare @dailyrate bigint = (select (SUM(transactionitemsmigrated)/@numofdays) from Transactions where projectid = @projid)
declare @complete bigint = (select SUM(transactionitemsmigrated) from transactions where projectid = @projid)
declare @daysremaining int = (select (CAST(GETDATE() AS int) + ((@projsize-@complete)/@dailyrate)))
;WITH cte AS (
select
[ID] = 1,
[Project] = (select projectname from projects where projectid = @projid),
[TotalItems] = @projsize,
[DaysActive] = @numofdays,
[DailyRate] = @dailyrate,
[TotalComplete] = @complete,
[ItemsRemaining] = @projsize - @complete,
[DaysRemaining] = ((@projsize-@complete)/@dailyrate),
[CompDate] = CAST(CAST(@daysremaining AS datetime) AS date)
UNION ALL
select
[ID] + 1,
[Project] = (select projectname from projects where projectid = @projid),
[TotalItems] = @projsize,
[DaysActive] = @numofdays,
[DailyRate] = @dailyrate,
[TotalComplete] = @complete,
[ItemsRemaining]= @projsize - @complete,
[DaysRemaining] = ((@projsize-@complete)/@dailyrate),
[CompDate] = CAST(CAST(@daysremaining AS datetime) AS date)
from cte
where [ID] < @maxid
)
select *
from cte
where @projid <= @maxid
OPTION (MAXRECURSION 100)
编辑:知道了。这是我用过的。非常感谢@Amit-Sukralia 的评论让我找到了解决方案!
SELECT
[Project] = projectName,
[TotalItems] = projectsizeexpitem,
[DaysActive] = (select DATEDIFF(DAY, MIN(starttime), GETDATE()) from transactions where projectid = p.projectid),
[DailyRate] = (select (SUM(transactionitemsmigrated)/(DATEDIFF(DAY, MIN(starttime), GETDATE()) )) from Transactions where projectid = p.projectid),
[TotalComplete] = (select SUM(transactionitemsmigrated) from transactions where projectid = p.projectid),
[ItemsRemaining] = projectsizeexpitem - (select SUM(transactionitemsmigrated) from transactions where projectid = p.projectid),
[ExpectedCompDate] = CAST((GETDATE() + ((p.projectsizeexpitem-(select SUM(transactionitemsmigrated) from transactions where projectid = p.projectid))/
(select (SUM(transactionitemsmigrated)/(DATEDIFF(DAY, MIN(starttime), GETDATE()) )) from Transactions where projectid = p.projectid))) as int) - CAST(GETDATE() as int)
FROM Projects p
您可以试试下面的方法。它不需要 CTE:
SELECT
ROW_NUMBER() OVER (PARTITION BY projectid) AS ID,
projectName AS [Project],
(select max(projectid) from Projects) AS MaxId,
projectsizeexpitem AS [TotalItems],
(select DATEDIFF(DAY, MIN(starttime), GETDATE()) from transactions where projectid = p.projectid) AS [DaysActive],
(select (SUM(transactionitemsmigrated)/(DATEDIFF(DAY, MIN(starttime), GETDATE()) )) from Transactions where projectid = p.projectid) AS [DailyRate],
(select SUM(transactionitemsmigrated) from transactions where projectid = p.projectid) AS [TotalComplete],
projectsizeexpitem - (select SUM(transactionitemsmigrated) from transactions where projectid = p.projectid) AS [ItemsRemaining],
(select (CAST(GETDATE() AS int) + ((projectsizeexpitem - (select SUM(transactionitemsmigrated) from transactions where projectid = p.projectid))/
(select (SUM(transactionitemsmigrated)/(DATEDIFF(DAY, MIN(starttime), GETDATE()) )) from Transactions where projectid = p.projectid)))) AS [DaysRemaining]
from Projects p
我在将 TSQL 查询转换为 cte 时遇到问题。我很确定这是一个候选人。我在其他查询中使用过 cte,但这个查询必须从多个来源获取数据,这让我有些伤心。这是我得到的有效方法:
declare @projid int = 0
declare @proj varchar = (select projectid from Projects where projectid = @projid)
declare @maxid int = (select max(projectid) from Projects)
declare @projsize bigint = (select projectsizeexpitem from Projects where projectid = @projid)
declare @numofdays int = (select DATEDIFF(DAY, MIN(starttime), GETDATE()) from transactions where projectid = @projid)
declare @dailyrate bigint = (select (SUM(transactionitemsmigrated)/@numofdays) from Transactions where projectid = @projid)
declare @complete bigint = (select SUM(transactionitemsmigrated) from transactions where projectid = @projid)
declare @daysremaining int = (select (CAST(GETDATE() AS int) + ((@projsize-@complete)/@dailyrate)))
WHILE @projid < @maxid
BEGIN
IF @projid IN (select projectid from projects)
BEGIN
set @proj = (select projectname from Projects where projectid = @projid)
set @maxid = (select max(projectid) from Projects)
set @projsize = (select projectsizeexpitem from Projects where projectid = @projid)
set @numofdays = (select DATEDIFF(DAY, MIN(starttime), GETDATE()) from transactions where projectid = @projid)
set @dailyrate = (select (SUM(transactionitemsmigrated)/@numofdays) from Transactions where projectid = @projid)
set @complete = (select SUM(transactionitemsmigrated) from transactions where projectid = @projid)
set @daysremaining = (select (CAST(GETDATE() AS int) + ((@projsize-@complete)/@dailyrate)))
select
[Project] = (select projectname from projects where projectid = @projid),
[TotalItems] = @projsize,
[DaysActive] = @numofdays,
[DailyRate] = @dailyrate,
[TotalComplete] = @complete,
[ItemsRemaining] = @projsize - @complete,
[DaysRemaining] = ((@projsize-@complete)/@dailyrate),
[CompDate] = CAST(CAST(@daysremaining AS datetime) AS date)
SET @projid = @projid + 1
END
ELSE
BEGIN
SET @projid = @projid + 1
END
END
这个问题是 returns SELECT 语句的每次迭代作为单独的结果 table。我想把它们放在一起进行聚合。这是我尝试过的:
declare @projid int = 0
declare @proj varchar = (select projectid from Projects where projectid = @projid)
declare @maxid int = (select max(projectid) from Projects)
declare @projsize bigint = (select projectsizeexpitem from Projects where projectid = @projid)
declare @numofdays int = (select DATEDIFF(DAY, MIN(starttime), GETDATE()) from transactions where projectid = @projid)
declare @dailyrate bigint = (select (SUM(transactionitemsmigrated)/@numofdays) from Transactions where projectid = @projid)
declare @complete bigint = (select SUM(transactionitemsmigrated) from transactions where projectid = @projid)
declare @daysremaining int = (select (CAST(GETDATE() AS int) + ((@projsize-@complete)/@dailyrate)))
;WITH cte AS (
select
[ID] = 1,
[Project] = (select projectname from projects where projectid = @projid),
[TotalItems] = @projsize,
[DaysActive] = @numofdays,
[DailyRate] = @dailyrate,
[TotalComplete] = @complete,
[ItemsRemaining] = @projsize - @complete,
[DaysRemaining] = ((@projsize-@complete)/@dailyrate),
[CompDate] = CAST(CAST(@daysremaining AS datetime) AS date)
UNION ALL
select
[ID] + 1,
[Project] = (select projectname from projects where projectid = @projid),
[TotalItems] = @projsize,
[DaysActive] = @numofdays,
[DailyRate] = @dailyrate,
[TotalComplete] = @complete,
[ItemsRemaining]= @projsize - @complete,
[DaysRemaining] = ((@projsize-@complete)/@dailyrate),
[CompDate] = CAST(CAST(@daysremaining AS datetime) AS date)
from cte
where [ID] < @maxid
)
select *
from cte
where @projid <= @maxid
OPTION (MAXRECURSION 100)
编辑:知道了。这是我用过的。非常感谢@Amit-Sukralia 的评论让我找到了解决方案!
SELECT
[Project] = projectName,
[TotalItems] = projectsizeexpitem,
[DaysActive] = (select DATEDIFF(DAY, MIN(starttime), GETDATE()) from transactions where projectid = p.projectid),
[DailyRate] = (select (SUM(transactionitemsmigrated)/(DATEDIFF(DAY, MIN(starttime), GETDATE()) )) from Transactions where projectid = p.projectid),
[TotalComplete] = (select SUM(transactionitemsmigrated) from transactions where projectid = p.projectid),
[ItemsRemaining] = projectsizeexpitem - (select SUM(transactionitemsmigrated) from transactions where projectid = p.projectid),
[ExpectedCompDate] = CAST((GETDATE() + ((p.projectsizeexpitem-(select SUM(transactionitemsmigrated) from transactions where projectid = p.projectid))/
(select (SUM(transactionitemsmigrated)/(DATEDIFF(DAY, MIN(starttime), GETDATE()) )) from Transactions where projectid = p.projectid))) as int) - CAST(GETDATE() as int)
FROM Projects p
您可以试试下面的方法。它不需要 CTE:
SELECT
ROW_NUMBER() OVER (PARTITION BY projectid) AS ID,
projectName AS [Project],
(select max(projectid) from Projects) AS MaxId,
projectsizeexpitem AS [TotalItems],
(select DATEDIFF(DAY, MIN(starttime), GETDATE()) from transactions where projectid = p.projectid) AS [DaysActive],
(select (SUM(transactionitemsmigrated)/(DATEDIFF(DAY, MIN(starttime), GETDATE()) )) from Transactions where projectid = p.projectid) AS [DailyRate],
(select SUM(transactionitemsmigrated) from transactions where projectid = p.projectid) AS [TotalComplete],
projectsizeexpitem - (select SUM(transactionitemsmigrated) from transactions where projectid = p.projectid) AS [ItemsRemaining],
(select (CAST(GETDATE() AS int) + ((projectsizeexpitem - (select SUM(transactionitemsmigrated) from transactions where projectid = p.projectid))/
(select (SUM(transactionitemsmigrated)/(DATEDIFF(DAY, MIN(starttime), GETDATE()) )) from Transactions where projectid = p.projectid)))) AS [DaysRemaining]
from Projects p