简体   繁体   English

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

[英]Convert ugly T SQL query to CTE

I'm having trouble making my TSQL query into a cte. 我在将TSQL查询转换为cte时遇到了麻烦。 I'm pretty sure it's a candidate for that. 我很确定这是一个候选人。 I've used cte's in other queries, but this one has to get data from multiple sources and that's causing me some grief. 我在其他查询中使用了cte,但是此查询必须从多个来源获取数据,这让我有些痛苦。 Here's what I've got that works: 这是我能工作的:

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

The problem with this one is that it returns each iteration of the SELECT statement as a separate results table. 这个问题是,它将SELECT语句的每个迭代作为单独的结果表返回。 I'd like to have them all together for aggregation. 我想将它们放在一起进行汇总。 Here's what I've tried: 这是我尝试过的:

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)

EDIT: Got it. 编辑:知道了。 Here's what I used. 这是我用的。 Big thanks to @Amit-Sukralia for his comment that got me to the solution! 非常感谢@ 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

You can try something like below. 您可以尝试以下类似方法。 It doesn't require a CTE: 它不需要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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM