SQL中的别名名称问题

时间:2014-08-23 05:06:21

标签: sql-server tsql

我正在尝试为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,

6 个答案:

答案 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中的一个已知限制,但不知道它是否是一个错误,有意或甚至是标准的一部分。但事实是,WHEREHAVING子句都不接受别名作为其条件的一部分,您必须仅使用原始源表中的列,这意味着对于按计算表达式进行过滤,您必须在SELECTWHERE部分中复制粘贴相同的内容。

避免这种重复的解决方法可以是使用子查询或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个)。

  • 在其中一个Subquery BigSpenders中,它获得了花费超过25000美元的所有客户。
  • 另一个子查询计算每个订单的总金额。
  • 然后它通过OrderDate和OrderID获得所有订单的排名。
  • 然后按每个客户的前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;