解析mysql函数,根据另一列检索每个类别的行

时间:2012-02-05 19:11:03

标签: mysql

我有一个包含众多列的表格,包括类别和评级。在整个表中,有两个类别值:类别1和类别2.评级值范围从1到5.以下anayltic查询检索每个评级的4个产品,不论其类别,因此,4个评级为1的产品,4个产品与等级2等等......(id> 10)没有特别重要的意义)

    SELECT 
      DISTINCT x.* 
    FROM 
      (SELECT   t.*, 
                  CASE WHEN @rating != t.rating THEN @rownum := 1 
                     ELSE @rownum := @rownum + 1 END 
                AS rank, 
                  @rating := t.rating
                AS var_rating 
       FROM products t 
       JOIN (
             SELECT @rownum := NULL, @rating := ''
                   ) r 
              WHERE ( id > 10 ) 
              ORDER BY t.rating, price
            ) x
     WHERE 
        x.rank <= 4

我希望修改它以检索每个类别的每个评级的4个产品。请有人帮忙。

非常感谢

1 个答案:

答案 0 :(得分:0)

This page在“select-n-per-group”问题上非常棒。

我基本上在我的解决方案中遵循它。

这些查询选择每个(类别,评级)最便宜的4种产品。在价格平局的情况下,它选择具有较小ID的那个。 如果您只想要4个产品(类别,评级)而不考虑价格,请跳过p.price<=products.price行。

方法1(易于理解):

SELECT *
FROM products
where (
   select count(*) from products as p
   where p.category = products.category 
     and p.rating = products.rating
     and p.price <= products.price
     and p.id < products.id             -- in case of tie with price
) < 4
ORDER BY category,rating,price;

内部查询说要计算有多少物品比你便宜或者价格相同,而外部查询说只挑选比你价格低于/等价物少于4件的物品。

如果您想使用用户变量,可以尝试:

SET @num := 0, @cat := '', @rating := '';
SELECT category,rating,id,price
FROM (
   SELECT category,rating,id,price,
      @num := if(@cat = category AND @rating=rating, @num + 1, 1) as row_number,
      @cat := category as dummy,
      @rating := rating as dummy2
  FROM products
  ORDER BY category,rating,price,id
) AS p WHERE p.row_number <= 4;

内部查询按类别,评级,价格和ID对您的表进行排序,并在每个(类别,评级)对中分配行号。外部查询从每个中选择前4个。


该页面上的最后一个方法会有这个查询,但是它不起作用,除非你的列上有某种索引(我的MySQL foo不足以解决它) :

ALTER TABLE products ADD KEY(???);

SET @num := 0, @cat := '', @rating := '';
SELECT category,rating,id,price,
      @num := if(@cat = category AND @rating=rating, @num + 1, 1) as row_number,
      @cat := category as dummy,
      @rating := rating as dummy2
FROM products FORCE INDEX (???)
GROUP BY category,rating, ???
HAVING row_number <= 2;

据说依赖于MYSQL在ORDER BY中执行GROUP BY,因此确保按要求排序行。