每组生成n行

时间:2015-05-08 18:54:40

标签: sql greatest-n-per-group

众所周知,GROUP BY每组产生一行。我想每组产生多行。例如,特定用例是为每个项目选择两种最便宜的产品。

对于该组中的两个或三个元素来说,这是微不足道的:

select type, variety, price
from fruits
where price = (select min(price) from fruits as f where f.type = fruits.type)
   or price = (select min(price) from fruits as f where f.type = fruits.type
      and price > (select min(price) from fruits as f2 where f2.type = fruits.type));

Select n rows per group in mysql

但我正在寻找一个可以在每个组中显示n行的查询,其中n是任意大的。换句话说,每个组显示5行的查询应该可以转换为每组显示7行的查询,只需替换其中的一些常量。

我不受任何DBMS约束,因此我对任何DBMS上运行的任何解决方案感兴趣。如果它使用一些非标准语法就可以了。

4 个答案:

答案 0 :(得分:3)

对于任何支持分析函数\窗函数的数据库,这都相对容易

select *
  from (select type, 
               variety, 
               price,
               rank() over ([partition by something]
                            order by price) rnk
          from fruits) rank_subquery
 where rnk <= 3

如果省略[partition by something],您将获得排名前三的行。如果您希望每个type排名前三,那么您partition by type函数中就会rank()

根据您要处理关系的方式,您可能希望使用dense_rank()row_number()而不是rank()。如果首先使用rank将两行绑定,则下一行的rnk为3,而rnk的{​​{1}}为dense_rank。在这两种情况下,两个绑定行的rnk都为row_numberrnk会随意给两个绑定行中的一行rnk为1,另一行为<input type="hidden" name="propHosp" value="0"> <input type="checkbox" name="propHosp" <? if($propHosp == "1") echo "checked='checked'"; ?> value="1"> 2。

答案 1 :(得分:2)

为了节省任何寻找时间的人,在撰写本文时,显然这不起作用,因为https://dev.mysql.com/doc/refman/5.7/en/subquery-restrictions.html

我从未成为相关子查询的粉丝,因为我看到的大多数用法通常都可以更简单地编写,但我认为这已经改变了......一点点。 (这适用于MySQL。)

SELECT `type`, `variety`, `price`
FROM `fruits` AS f2
WHERE `price` IN (
   SELECT DISTINCT `price` 
   FROM `fruits` AS f1 
   WHERE f1.type = f2.type
   ORDER BY `price` ASC
   LIMIT X
   )
;

其中X是您想要的“任意”值。

如果您知道在价格重复的情况下如何进一步限制,并且数据允许这样的限制......

SELECT `type`, `variety`, `price`
FROM `fruits` AS f2
WHERE (`price`, `other_identifying_criteria`) IN (
   SELECT DISTINCT `price`, `other_identifying_criteria`
   FROM `fruits` AS f1 
   WHERE f1.type = f2.type
   ORDER BY `price` ASC, `other_identifying_criteria` [ASC|DESC]
   LIMIT X
   )
;

答案 2 :(得分:1)

&#34;每组最大N问题&#34;可以使用窗口函数轻松解决:

select type, variety, price
from (
  select type, variety, price,
         dense_rank() over (partition by type) order by price as rnk
  from fruits
) t
where rnk <= 5;

答案 3 :(得分:1)

Windows功能仅适用于SQL Server 2012及更高版本。试试这个:

SQL Server 2005及以上解决方案

DECLARE @yourTable TABLE(Category VARCHAR(50), SubCategory VARCHAR(50), price INT)
INSERT INTO @yourTable
VALUES  ('Meat','Steak',1),
        ('Meat','Chicken Wings',3),
        ('Meat','Lamb Chops',5);

DECLARE @n INT = 2;

SELECT DISTINCT Category,CA.SubCategory,CA.price
FROM @yourTable A
CROSS APPLY
(
    SELECT TOP (@n) SubCategory,price
    FROM @yourTable B
    WHERE A.Category = B.Category
    ORDER BY price DESC
) CA

每个类别中两个价格最高的子类别的结果:

Category                  SubCategory               price
------------------------- ------------------------- -----------
Meat                      Chicken Wings             3
Meat                      Lamb Chops                5