问题
I'm using the SQLBook database from the Data Analysis Using SQL and Excel book to display the average days to ship for states that have higher than average overall shipping days. I'm using 2 common table expressions:
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
The problem is I keep getting a "The multi-part identifier "AvgShipping.avgShip" could not be bound" error. Please let me know where the problem with this query is.
Thanks!
回答1:
You're not selecting from AvgShpping anywhere. Try
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:
You would need to put AvgShipping
in the from
clause of the outer query so you can then use its column:
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
But I think this task can be done more efficiently with window functions:
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
We can simplify the logic a little by avoiding aggregation and using distinct
instead:
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
来源:https://stackoverflow.com/questions/63908896/identifier-could-not-be-bound-in-multiple-common-table-expressions