【问题标题】:Multiple columns are specified in an aggregated expression containing an outer reference TSQL在包含外部引用 TSQL 的聚合表达式中指定了多个列
【发布时间】:2014-05-17 04:03:27
【问题描述】:

我有以下疑问:

SELECT 
    FileNumber, 
    dbo.GetLocalDateTimeFunc(SentDate) AS SentDate 
INTO #tmp1
FROM FileMain f 
JOIN FileActions fa ON f.FileID = fa.FileID
WHERE ActionDefID = 15 AND SentDate IS NOT NULL

SELECT 
    FileNumber, 
    dbo.GetLocalDateTimeFunc(ReceivedDate) AS ReceivedDate 
INTO #tmp2
FROM FileMain f 
JOIN FileActions fa ON f.FileID = fa.FileID
WHERE ActionDefID = 23 AND ReceivedDate IS NOT NULL

SELECT DISTINCT 
    o.Name AS Company, fm.FileNumber, pc.Name as Client, 
    p.State, c.County, t1.SentDate, t2.ReceivedDate,
(SELECT sum(case    
        when dateadd(day, datediff(day, 0, t1.SentDate), 0) = dateadd(day, datediff(day, 0, t2.ReceivedDate), 0) then
            datediff(second, t1.SentDate, t2.ReceivedDate)
        when [DATE] = dateadd(day, datediff(day, 0, t1.SentDate), 0) then
            case    
            when t1.SentDate > [DATE] + begin_time then datediff(second, t1.SentDate, [DATE] + end_time)
            else duration
            end
        when [DATE] = dateadd(day, datediff(day, 0, t2.ReceivedDate), 0) then
            case    
            when t2.ReceivedDate    <  [DATE] + end_time then datediff(second, [DATE] + begin_time, t2.ReceivedDate)
            else duration
            end
        else duration
        end
          ) 
        / 60.0 / 60.0
    FROM F_TABLE_DATE(t1.SentDate, t2.ReceivedDate) d 
    INNER JOIN Unisource_Calendar c ON d.WEEKDAY_NAME_LONG = c.day_name)
FROM Office o
JOIN PartnerCompany pc ON o.OfficeID = pc.OfficeID
JOIN FileMain fm ON o.OfficeID = fm.OfficeID AND pc.PartnerCompanyID = fm.ClientID
JOIN Property p ON p.FileID = fm.FileID
JOIN County c ON p.CountyID = c.CountyID
JOIN FileActions fa ON fm.FileID = fa.FileID
JOIN #tmp1 t1 ON t1.FileNumber = fm.FileNumber
JOIN #tmp2 t2 ON t2.FileNumber = fm.FileNumber
WHERE p.State IN ('AR', 'CA', 'CO', 'DE', 'DC', 'FL', 'GA', 'IL', 'IN', 'IA', 'KS', 'KY', 'LA', 'MD', 'MA', 'MI', 'MN', 'MS', 'MO', 'MT', 'NE', 'NJ', 'NV', 'NH', 'NY', 'NC', 'ND', 'OH', 'OK', 'PA', 'RI', 'SC', 'TN', 'TX', 'VA', 'WV', 'WI')
ORDER BY SentDate, FileNumber DESC

我的子查询出现以下错误:

在包含外部引用的聚合表达式中指定了多个列。如果要聚合的表达式包含外部引用,则该外部引用必须是表达式中引用的唯一列。

有人知道如何解决这个问题吗?

或者,如果有人有一个功能可以计算日期时间差异,同时排除营业时间和周末,这也会有所帮助。谢谢!

【问题讨论】:

  • 您可以尝试将 (SELECT SUM() ...) 子查询转换为 OUTER APPLY 子句。

标签: sql sql-server tsql


【解决方案1】:

我建议您首先使用 CTE 简化代码(枚举所有表会分散注意力以给出精确的语句)。此外,您应该尝试将聚合 SUM 函数作为 PARTITION by expression 的一部分。这可能有助于避免您提到的问题。

【讨论】:

  • 我对 CTE 不是很熟悉。实际上,我也不是高级 SQL 开发人员,正如您从我的代码中看到的那样。关于创建 CTE,您对我有什么建议吗?
【解决方案2】:

据我所知,表函数 F_Table_Date 在两个参数之间的每一天都返回 DATE 或 DATETIME 行,而 UnisourceCalendar 可能是工作日列表(分配给您提到的假期)。如果是这种情况,并且 UnisourceCalendar 还返回 DATE 或 DATETIME 列,请考虑为您的子查询:

SELECT (COUNT(*) * 60*60*24)
  + (
     SELECT COUNT(*)
     FROM UnisourceCalendar
     WHERE [DATE] = CAST(CONVERT(VARCHAR,t1.SentDate+1,112) AS DATETIME)
    )*DATEDIFF(SS,t1.SentDate,CAST(CONVERT(VARCHAR,t1.SentDate+1,112) AS DATETIME))
  + (
     SELECT COUNT(*)
     FROM UnisourceCalendar
     WHERE [DATE] = CAST(CONVERT(VARCHAR,t1.SentDate+1,112) AS DATETIME)
    )*DATEDIFF(SS,CAST(CONVERT(VARCHAR,t2.ReceivedDate,112) AS DATETIME),t2.ReceivedDate)
FROM UnisourceCalendar C
WHERE C.[DATE] > t1.SentDate AND C.[DATE] < t2.ReceivedDate
GROUP BY t1.SentDate, t2.ReceivedDate

这里有什么:

  1. 假设 UnisourceCalendar 每个工作日有 1 行,则任何其他联接都是多余的。
  2. 那么,计数就足够了。
  3. 使用样式 112 将一个日期的转换/转换值与自身相比较的 datediff 会去除超时并重新转换为午夜,从而使我们能够从发送日期和上一个午夜获取秒到下一个午夜接收日期,但前提是每个日期都在单源日历中(乘以计数,如果为 0,则不添加秒数,如果为 1,则添加额外的秒数)。
  4. 输出假定您将按原样将结果划分为子查询之外的小时。

复杂吗?当然可以,但它应该以相对较短的顺序输出您正在寻找的结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-18
    • 1970-01-01
    • 1970-01-01
    • 2020-03-17
    相关资源
    最近更新 更多