1. 程式人生 > 其它 >mysql分組取每組前幾條記錄(排序)

mysql分組取每組前幾條記錄(排序)

表mygoods為商品表,cat_id為分類id,goods_id為商品id,status為商品當前的狀態位(1:有效,0:無效)。

CREATE TABLE `mygoods` (  
  `goods_id` int(11) unsigned NOT NULL AUTO_INCREMENT,  
  `cat_id` int(11) NOT NULL DEFAULT '0',  
  `price` tinyint(3) NOT NULL DEFAULT '0',  
  `status` tinyint(3) DEFAULT '1',  
  PRIMARY KEY (`goods_id`),  
  
KEY `icatid` (`cat_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `mygoods` VALUES (1, 101, 90, 0); INSERT INTO `mygoods` VALUES (2, 101, 99, 1); INSERT INTO `mygoods` VALUES (3, 102, 98, 0); INSERT INTO `mygoods` VALUES (4, 103, 96, 0); INSERT INTO `mygoods` VALUES (5, 102, 95, 0);
INSERT INTO `mygoods` VALUES (6, 102, 94, 1); INSERT INTO `mygoods` VALUES (7, 102, 93, 1); INSERT INTO `mygoods` VALUES (8, 103, 99, 1); INSERT INTO `mygoods` VALUES (9, 103, 98, 1); INSERT INTO `mygoods` VALUES (10, 103, 97, 1); INSERT INTO `mygoods` VALUES (11, 104, 96, 1); INSERT INTO `mygoods` VALUES
(12, 104, 95, 1); INSERT INTO `mygoods` VALUES (13, 104, 94, 1); INSERT INTO `mygoods` VALUES (15, 101, 92, 1); INSERT INTO `mygoods` VALUES (16, 101, 93, 1); INSERT INTO `mygoods` VALUES (17, 101, 94, 0); INSERT INTO `mygoods` VALUES (18, 102, 99, 1); INSERT INTO `mygoods` VALUES (19, 105, 85, 1); INSERT INTO `mygoods` VALUES (20, 105, 89, 0); INSERT INTO `mygoods` VALUES (21, 105, 99, 1);

先查出分組後的有效商品

SELECT
    a.* 
FROM
    mygoods a 
WHERE
    a.`status` = 1 
GROUP BY
    a.cat_id,
    a.goods_id,
    a.price 
ORDER BY
    cat_id;

+----------+--------+-------+--------+
| goods_id | cat_id | price | status |
+----------+--------+-------+--------+
|        2 |    101 |    99 |      1 |
|       15 |    101 |    92 |      1 |
|       16 |    101 |    93 |      1 |
|        6 |    102 |    94 |      1 |
|        7 |    102 |    93 |      1 |
|       18 |    102 |    99 |      1 |
|        8 |    103 |    99 |      1 |
|        9 |    103 |    98 |      1 |
|       10 |    103 |    97 |      1 |
|       11 |    104 |    96 |      1 |
|       12 |    104 |    95 |      1 |
|       13 |    104 |    94 |      1 |
|       19 |    105 |    85 |      1 |
|       21 |    105 |    99 |      1 |
+----------+--------+-------+--------+

需求一:每個分類下,找出兩個價格最高的有效的商品。

1. 每個分類找出價格最高的兩個商品(錯誤,沒有滿足有效商品)

複製程式碼
mysql> select a.*   
    -> from mygoods a   
    -> where (select count(*) 
    -> from mygoods 
    -> where cat_id = a.cat_id and price > a.price  ) <2 
    -> order by a.cat_id,a.price desc;
+----------+--------+-------+--------+
| goods_id | cat_id | price | status |
+----------+--------+-------+--------+
|        2 |    101 |    99 |      1 |
|       17 |    101 |    94 |      0 |
|       18 |    102 |    99 |      1 |
|        3 |    102 |    98 |      0 |
|        8 |    103 |    99 |      1 |
|        9 |    103 |    98 |      1 |
|       11 |    104 |    96 |      1 |
|       12 |    104 |    95 |      1 |
|       21 |    105 |    99 |      1 |
|       20 |    105 |    89 |      0 |
+----------+--------+-------+--------+
10 rows in set (0.00 sec)

2. 每個分類找出價格最高的有效的兩個商品(正確)

SELECT
    a.* 
FROM
    mygoods a 
WHERE
    (
    SELECT
        count( 1 ) 
    FROM
        mygoods b
    WHERE
        a.cat_id = b.cat_id 
        AND b.price > a.price 
        AND b.`status` = 1 
    )< 2 
    AND a.`status` = 1 
ORDER BY
    a.cat_id,
    a.price DESC

+----------+--------+-------+--------+ | goods_id | cat_id | price | status | +----------+--------+-------+--------+ | 2 | 101 | 99 | 1 | | 16 | 101 | 93 | 1 | | 18 | 102 | 99 | 1 | | 6 | 102 | 94 | 1 | | 8 | 103 | 99 | 1 | | 9 | 103 | 98 | 1 | | 11 | 104 | 96 | 1 | | 12 | 104 | 95 | 1 | | 21 | 105 | 99 | 1 | | 19 | 105 | 85 | 1 | +----------+--------+-------+--------+ 10 rows in set (0.00 sec)

3. 每個分類找出價格最高的有效的兩個商品(正確)

SELECT
    a.*
FROM
    mygoods a
    LEFT JOIN mygoods b ON a.cat_id = b.cat_id 
    AND a.price < b.price 
    AND b.`status` = 1 
WHERE
    a.`status` = 1 
GROUP BY
    a.goods_id,
    a.cat_id,
    a.price 
HAVING
    count( b.goods_id ) < 2
ORDER BY
    a.cat_id,
    a.price DESC;

+----------+--------+-------+--------+
| goods_id | cat_id | price | status |
+----------+--------+-------+--------+
|        2 |    101 |    99 |      1 | 
|       16 |    101 |    93 |      1 | 
|       18 |    102 |    99 |      1 | 
|        6 |    102 |    94 |      1 | 
|        8 |    103 |    99 |      1 | 
|        9 |    103 |    98 |      1 | 
|       11 |    104 |    96 |      1 | 
|       12 |    104 |    95 |      1 | 
|       21 |    105 |    99 |      1 | 
|       19 |    105 |    85 |      1 | 
+----------+--------+-------+--------+
10 rows in set (0.00 sec)

4.每個分類找出價格最高的有效的兩個商品(錯誤)

SELECT
    a.* 
FROM
    mygoods a 
WHERE
    (
    SELECT
        count( * ) 
    FROM
        mygoods b
    WHERE
        a.cat_id = b.cat_id 
        AND b.price > a.price 
        #AND b.`status` = 1 
    )< 2 
    AND a.`status` = 1 
ORDER BY
    a.cat_id,
    a.price DESC

+----------+--------+-------+--------+
| goods_id | cat_id | price | status |
+----------+--------+-------+--------+
|        2 |    101 |    99 |      1 |
|       18 |    102 |    99 |      1 |
|        8 |    103 |    99 |      1 |
|        9 |    103 |    98 |      1 |
|       11 |    104 |    96 |      1 |
|       12 |    104 |    95 |      1 |
|       21 |    105 |    99 |      1 |
+----------+--------+-------+--------+
7 rows in set (0.00 sec)

需求二:每個分類下,找出兩個價格最低的有效的商品。

方法一:

SELECT
    a.* 
FROM
    mygoods a 
WHERE
    (
    SELECT
        count( * ) 
    FROM
        mygoods b
    WHERE
        a.cat_id = b.cat_id 
        AND b.price < a.price 
        AND b.`status` = 1 
    )< 2 
    AND a.`status` = 1 
ORDER BY
    a.cat_id,
    a.price DESC

+----------+--------+-------+--------+
| goods_id | cat_id | price | status |
+----------+--------+-------+--------+
|       16 |    101 |    93 |      1 |
|       15 |    101 |    92 |      1 |
|        6 |    102 |    94 |      1 |
|        7 |    102 |    93 |      1 |
|        9 |    103 |    98 |      1 |
|       10 |    103 |    97 |      1 |
|       12 |    104 |    95 |      1 |
|       13 |    104 |    94 |      1 |
|       21 |    105 |    99 |      1 |
|       19 |    105 |    85 |      1 |
+----------+--------+-------+--------+
10 rows in set (0.00 sec)

方法二:

SELECT
    a.* 
FROM
    mygoods a
    LEFT JOIN mygoods b ON a.cat_id = b.cat_id 
    AND a.price > b.price 
    AND b.`status` = 1 
WHERE
    a.`status` = 1 
GROUP BY
    a.goods_id,
    a.cat_id,
    a.price 
HAVING
    count( b.goods_id ) < 2 
ORDER BY
    a.cat_id,
    a.price DESC;

+----------+--------+-------+--------+
| goods_id | cat_id | price | status |
+----------+--------+-------+--------+
|       16 |    101 |    93 |      1 |
|       15 |    101 |    92 |      1 |
|        6 |    102 |    94 |      1 |
|        7 |    102 |    93 |      1 |
|        9 |    103 |    98 |      1 |
|       10 |    103 |    97 |      1 |
|       12 |    104 |    95 |      1 |
|       13 |    104 |    94 |      1 |
|       21 |    105 |    99 |      1 |
|       19 |    105 |    85 |      1 |
+----------+--------+-------+--------+

具體的原理本人沒搞清楚,誰有比較好的思路可以交流下

參考文章:

mysql分組取每組前幾條記錄(排序)