涉及MAX()的更简洁的SQL查询

时间:2013-03-13 11:16:08

标签: mysql sql sql-server subquery max

inventory
+------------------+-------------------+------------+
| DVD              | replacement_price |      stock |
+------------------+-------------------+------------+
| Pi               |              9.99 |        500 |
| Dune             |             29.99 |        100 |
| Heathers         |              4.99 |         20 |
| Jaws             |             19.99 |        500 |
| Mulholland_Drive |             39.99 |         50 |
| Waking_Life      |             29.99 |        200 |
+------------------+-------------------+------------+

rented
+-----------------+-----------+------------------+
| subscriber      | queue_nbr | DVD              |
+-----------------+-----------+------------------+
| Bob             |         1 | Mulholland_Drive |
| Bob             |         2 | Jaws             |
| Chey            |         1 | Pi               |
| Chey            |         2 | Heathers         |
| Jamie           |         2 | Mulholland_Drive |
| Jamie           |         4 | Dune             |
| Jamie           |         1 | Jaws             |
| Jamie           |         3 | Waking_Life      |
| Nora            |         4 | Jaws             |
| Nora            |         2 | Mulholland_Drive |
| Nora            |         3 | Dune             |
| Nora            |         1 | Waking_Life      |
+-----------------+-----------+------------------+

我想只返回拥有最昂贵电影队列的订阅者(如果您丢失了在给定时间播放的所有电影,请考虑Netflix DVD更换费用)。我使用MAX()而不是TOP,LIMIT或ROWNUM,因为查询需要尽可能与数据库无关,并且必须在出现平局时返回多个订阅者。使用上面的表格,结果应为

+---------+
| highest |
+---------+
| Jamie   |
| Nora    |
+---------+

经过大量的搜索和实验,我提出了可行的代码,但在新手眼中,无论是代码还是执行,我看起来都是臃肿而低效的。

有人会介意重构和解释您的代码吗?

我的代码:


SELECT z.subscriber highest
FROM 
(SELECT MAX(price) max_price
    FROM (
        SELECT subscriber_name subscriber, SUM(replacement_price) price
        FROM inventory i
        INNER JOIN rented r
        ON i.DVD = r.DVD
        GROUP BY subscriber
    ) x
) y
INNER JOIN
(
    SELECT subscriber_name subscriber, SUM(replacement_price) price
    FROM inventory i
    INNER JOIN rented r
    ON i.DVD = r.DVD
    GROUP BY subscriber
) z
ON z.price = y.max_price

2 个答案:

答案 0 :(得分:0)

SELECT z.subscriber
FROM(
    SELECT RANK() OVER(ORDER BY SUM(replacement_price)) subscriber_rank, 
           r.subscriber subscriber, 
           SUM(replacement_price) totalReplacementPrice
    FROM inventory i
    INNER JOIN rented r ON i.dvd = r.DVD
GROUP BY subscriber
) z
WHERE z.subscriber_rank = 1

您从sql示例查询时,有些列名称不同,所以我使用了演示表中给出的列名。我在内部查询中使用rank函数来查找按replacement_price的总和排序的所有人的顺序。然后选择排名为1的行。

排名在MS Sql Server和Oracle中均可用。要比@bluefeet更进一步说明你需要提供更多关于你所针对的数据库的详细信息。

答案 1 :(得分:0)

如果您只想返回总数为max的那些,那么您可以使用以下适用于MySQL和SQL Server的方法。它不比你当前的查询更简洁:

select subscriber
from inventory i
inner join rented r
  on i.dvd = r.dvd
group by subscriber
having sum(replacement_price) = (select max(TotalCost)
                                 from 
                                 (
                                   select sum(replacement_price) TotalCost
                                   from inventory i
                                   inner join rented r
                                     on i.dvd = r.dvd
                                   group by subscriber
                                  ) p);

如果您使用的是SQL Server,那么我建议实现窗口函数,类似于:

select subscriber
from
(
  select subscriber,
    rank() over(order by sum(replacement_price) desc) rnk
  from inventory i
  inner join rented r
    on i.dvd = r.dvd
  group by subscriber
) src
where rnk = 1

请参阅SQL Fiddle with Demo