将丑陋的T SQL查询转换为CTE

时间:2016-04-05 21:44:15

标签: sql sql-server common-table-expression

我在将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

这个问题是它将SELECT语句的每次迭代作为单独的结果表返回。我希望将它们聚集在一起进行聚合。以下是我尝试过的内容:

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

1 个答案:

答案 0 :(得分:1)

您可以尝试以下内容。它不需要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