【问题标题】:Identifier could not be bound in multiple common table expressions无法在多个公用表表达式中绑定标识符
【发布时间】:2020-09-15 19:47:54
【问题描述】:

我正在使用“使用 SQL 和 Excel 进行数据分析”一书中的 SQLBook 数据库来显示总发货天数高于平均发货天数的州的平均发货天数。我正在使用 2 个公用表表达式:

WITH orderDetails (days, state) 
AS(
    SELECT DATEDIFF(day, o.OrderDate, ol.ShipDate), o.State 
    FROM SQLBook.dbo.Orders o
    JOIN [SQLBook].dbo.OrderLines ol
    ON ol.OrderId = o.OrderId
)
,
/* This finds the overall average shipping days */
AvgShipping (avgShip)
AS(
    SELECT AVG(DATEDIFF(day, o.OrderDate, ol.ShipDate))
    FROM SQLBook.dbo.Orders o
    JOIN [SQLBook].dbo.OrderLines ol
    ON ol.OrderId = o.OrderId
)

SELECT
    state,
    AVG(days) AS "Average days to ship"
FROM orderDetails
GROUP BY state
HAVING AVG(days) > AvgShipping.avgShip
ORDER BY state

问题是我不断收到“无法绑定多部分标识符“AvgShipping.avgShip””错误。请让我知道这个查询的问题出在哪里。

谢谢!

【问题讨论】:

    标签: sql common-table-expression


    【解决方案1】:

    您不会在任何地方从 AvgShpping 中进行选择。试试

    WITH orderDetails (days, state) 
    AS(
        SELECT DATEDIFF(day, o.OrderDate, ol.ShipDate), o.State 
        FROM SQLBook.dbo.Orders o
        JOIN [SQLBook].dbo.OrderLines ol
        ON ol.OrderId = o.OrderId
    )
    ,
    /* This finds the overall average shipping days */
    AvgShipping (avgShip)
    AS(
        SELECT AVG(DATEDIFF(day, o.OrderDate, ol.ShipDate))
        FROM SQLBook.dbo.Orders o
        JOIN [SQLBook].dbo.OrderLines ol
        ON ol.OrderId = o.OrderId
    )
    
    SELECT
        state,
        AVG(days) AS "Average days to ship"
    FROM orderDetails
    GROUP BY state
    HAVING AVG(days) > (select avgShip from AvgShipping) 
    ORDER BY state
    

    【讨论】:

      【解决方案2】:

      您需要将AvgShipping 放在外部查询的from 子句中,这样您就可以使用它的列:

      WITH ...
      SELECT od.state, AVG(od.days) AS average_days_to_ship
      FROM orderDetails od
      CROSS JOIN AvgShipping s
      GROUP BY od.state, s.avgShip
      HAVING AVG(od.days) > s.avgShip
      ORDER BY od.state
      

      但我认为使用窗口函数可以更有效地完成这项任务:

      select *
      from (
          select state, 
              avg(datediff(day, o.orderdate, ol.shipdate)) as avg_days_state,
              1.0 * sum(sum(datediff(day, o.orderdate, ol.shipdate))) over() 
                  / sum(count(*)) over() as avg_days_overall
          from  sqlbook.dbo.orders o
          inner join sqlbook.dbo.orderlines ol on ol.OrderId = o.OrderId
          group by state
      ) t
      where avg_days_state > avg_days_overall
      

      我们可以通过避免聚合并改用distinct 来稍微简化逻辑:

      select distinct state, avg_days_state, avg_days_overall
      from (
          select state, 
              avg(datediff(day, o.orderdate, ol.shipdate)) over(partition by o.state) as avg_days_state,
              avg(datediff(day, o.orderdate, ol.shipdate)) over() as avg_days_overall
          from  sqlbook.dbo.orders o
          inner join sqlbook.dbo.orderlines ol on ol.OrderId = o.OrderId
      ) t
      where avg_days_state > avg_days_overall
      

      【讨论】:

        猜你喜欢
        • 2020-01-18
        • 2020-02-05
        • 1970-01-01
        • 2017-12-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-10
        相关资源
        最近更新 更多