我正在尝试为SQL Server示例数据库Northwind编写查询。问题是:"显示由Northwind花费超过25,000美元的客户购买的最近五个订单。"
在我的查询中,Alias名称 - " Amount"没有得到承认。我的查询如下:
select top(5) a.customerid, sum(b.unitprice*b.quantity) as "Amount", max(c.orderdate) as Orderdate
from customers a join orders c
on a.customerid = c.customerid
join [order details] b
on c.orderid = b.orderid
group by a.customerid
--having Amount > 25000 --throws error
having sum(b.unitprice*b.quantity) > 25000 --works, but I don't think that this is a good solution
order by Orderdate desc
请让我知道我在这里做错了什么,因为我是写T Sql的新手。此查询和我的逻辑也可以作为生产级别查询处理吗?
TIA,
答案 0 :(得分:1)
您必须在查询中使用聚合。这一切都与SELECT语句的执行顺序有关。 SELECT语句的语法如下:
SELECT
FROM
WHERE
GROUP BY
HAVING
ORDER BY
执行SELECT语句的顺序如下。由于SELECT子句直到HAVING子句之后才执行,因此不能像在ORDER BY子句中那样使用别名。
FROM
WHERE
GROUP BY
HAVING
SELECT
ORDER BY
参考文章:http://www.bennadel.com/blog/70-sql-query-order-of-operations.htm
答案 1 :(得分:0)
您必须使用Where b.unitprice*b.quantity > 25000
代替having Amount > 25000
。
已用于聚合条件。您的商家确定您的查询条件。如果您需要计算超过25000的价格总和,则必须使用Where b.unitprice*b.quantity > 25000
,如果您需要向总价超过25000的客户展示,则必须在查询中使用having Amount > 25000
。< / p>
select top(5) a.customerid, sum(b.unitprice*b.quantity) as Amount, max(c.orderdate) as Orderdate
from customers a
JOIN orders c ON a.customerid = c.customerid
join [order details] b ON c.orderid = b.orderid
group by a.customerid
having sum(b.unitprice*b.quantity) > 25000 --works, but I don't think that this is a good solution
Order by Amount
答案 2 :(得分:0)
Having
子句适用于SUM,MAX,AVG等聚合函数。
您可以尝试这样
SELECT TOP 5 customerid,SUM(Amount)Amount , MAX(Orderdate) Orderdate
FROM
(
SELECT A.customerid, (B.unitprice * B.quantity) As "Amount", C.orderdate As Orderdate
FROM customers A JOIN orders C ON A.customerid = C.customerid
JOIN [order details] B ON C.orderid = B.orderid
) Tmp
GROUP BY customerid
HAVING SUM(Amount) > 25000
ORDER BY Orderdate DESC
答案 3 :(得分:0)
这至少是SQL Server中的一个已知限制,但不知道它是否是一个错误,有意或甚至是标准的一部分。但事实是,WHERE
或HAVING
子句都不接受别名作为其条件的一部分,您必须仅使用原始源表中的列,这意味着对于按计算表达式进行过滤,您必须在SELECT
和WHERE
部分中复制粘贴相同的内容。
避免这种重复的解决方法可以是使用子查询或cte,并在别名只是“输入”表时对外部查询应用过滤器:
WITH TopOrders AS (
select a.customerid, sum(b.unitprice*b.quantity) as "Amount", max(c.orderdate) as Orderdate
from customers a join orders c
on a.customerid = c.customerid
join [order details] b
on c.orderid = b.orderid
group by a.customerid
--no filter here
order by Orderdate desc
)
SELECT TOP(5) * FROM TopOrders WHERE Amount > 25000 ;
有趣的是,ORDER BY
子句 直接接受别名。
答案 4 :(得分:0)
问题是小小的模糊。
显示客户购买的最近五个订单 在Northwind花了超过25,000美元。
是否要求所有在所有交易中花费超过25,000美元的客户(可能超过5个)显示最近的5个订单。
以下查询显示了在所有交易中花费25000美元的所有客户(不仅仅是最近的5个)。
-
SELECT *
FROM (SELECT C.customerid,
C.orderdate,
C.orderid,
B3.amount,
Row_number()
OVER(
partition BY C.customerid
ORDER BY C.orderdate DESC, C.orderid DESC) Rank
FROM orders C
JOIN
--Get Amount Spend Per Order
(SELECT b2.orderid,
Sum(b2.unitprice * b2.quantity) AS Amount
FROM [order details] b2
GROUP BY b2.orderid) B3
ON C.orderid = B3.orderid
JOIN
--Get Customers who spent more than 25000
(SELECT c.customerid
FROM orders c
JOIN [order details] b
ON c.orderid = b.orderid
GROUP BY c.customerid
HAVING Sum(b.unitprice * b.quantity) > 25000) BigSpenders
ON C.customerid = BigSpenders.customerid) X
WHERE X.rank <= 5
答案 5 :(得分:0)
我手头没有那个架构,所以表格&#39;和专栏&#39;名字可能有点误入歧途,但原则是一样的:
select top (5) ord2.*
from (
select top (1) ord.CustomerId
from dbo.Orders ord
inner join dbo.[Order Details] od on od.OrderId = ord.OrderId
group by ord.CustomerId
having sum(od.unitPrice * od.Quantity) > $25000
) sq
inner join dbo.Orders ord2 on ord2.CustomerId = sq.CustomerId
order by ord2.OrderDate desc;