2

我现在有点卡住了,可以使用一些快速的 MySQL 帮助。

假设我有一个包含产品评论的表格,列product_id, customer, date。现在,对于每个不同的产品,我想获得 3 条第一条评论。ORDER BY date 很简单,但我不知道如何为每个不同的 product_id 获取 3 个条目。由于都在同一张表中,INNER JOIN 没有任何意义,GROUP BY 也没有。那么,有什么想法吗?

编辑:我已经在 SQLFiddle 上成功使用了这个查询:

SELECT * FROM (
  SELECT customer, DATE, p_asin, @curTop := 
   CASE WHEN (
     @prevP_asin <> p_asin
   )
   THEN 1 
   ELSE @curTop +1
   END AS Top, @prevP_asin := p_asin
  FROM reviews2 r, (
    SELECT @curTop :=0
  ) A
 ORDER BY r.p_asin, r.date ) B
WHERE top <=3

但是由于某种原因,当我尝试将它应用到我在 PhpMyAdmin 中的表时,Top 的编号对于新产品不是从 1 开始,而是一起计数。Fiddle 和实际表的行为怎么会如此不同?

4

3 回答 3

1

仅当我们可以假设给定产品的日期值是唯一的时,以下内容才有效。如果这不是真的,那么您将需要在“p1.date < p.date”之后的 where 语句中添加一个唯一值,以便每一行都获得一个唯一的排名。

SQLFiddle在这里

SELECT * FROM (
    SELECT 
      product_id,
      customer, (
      select count(*) as cnt from products p1 
          where p1.product_id = p.product_id and
                p1.date < p.date
        ) rnk
    FROM  
      products P
    ORDER BY
      P.product_id, P.date
    ) A
  WHERE rnk < 3
于 2013-05-02T14:40:52.327 回答
0

在 Oracle 中,您可以使用 rank() over,但在 MySQL 中不可用。我使用这个页面来了解如何做到这一点:在 mysql 中排名

此外,它在SQLFiddle

SELECT * FROM (
SELECT 
  product_id,
  customer,
  @curRank := case when (@prevProductID <> product_id)
               then  1 else   @curRank + 1 
             end as Rnk,
  @prevProductID := product_id
FROM
   products p, (
     SELECT @curRank := 0
   ) r
ORDER BY
  P.product_id, P.date
) A
  WHERE Rnk <= 3
于 2013-05-01T17:54:59.213 回答
0

我知道这个问题已经有一段时间了,但是现在 SQL 8.0 已经发布了一段时间,我想我可能会补充一点,我们可以使用 ROW_NUMBER() 来按键列进行分区(OP 问题中的 product_id。)按另一列排序(OP问题中的日期。)

简而言之,我们要做的是:

  1. 加入有问题的表
  2. 按键列 (product_id) 和您想要的任何其他列排序。
  3. 为每条记录提供行号——重置键列的每个不同值的计数 [我们遇到的每个新 product_id]
  4. 使用上述步骤中的行号作为 WHERE 条件来选择第一个 n 行(例如,WHERE row_number <= 3 从键列中获取每个不同值的第一个 3 行)

例子:

SELECT FULL_TABLE.*
FROM (
         SELECT P.*,
                PD.*,
                ROW_NUMBER() over (
                    PARTITION BY P.id
                    ORDER BY P.date
                    ) AS row_num
         FROM Products AS P
                  LEFT JOIN ProductDetails AS PD on P.id = PD.productId
         ORDER BY P.id, row_num
     ) AS FULL_TABLE
WHERE row_num <= 3;
于 2020-04-20T16:35:23.897 回答