MySQL實現over partition by(分組后對組內數據排序)


前言

開發中遇到了這樣一個需求:統計商品庫存,產品ID + 子產品名稱都相同時,可以確定是同一款商品。當商品來自不同的渠道時,我們要統計每個渠道中最大的那一個。如果在Oracle中可以通過分析函數 OVER(PARTITION BY… ORDER BY…)來實現。在MySQL中應該怎么來實現呢。現在通過兩種簡單的方式來實現這一需求。
數據准備

/*Table structure for table `product_stock` */
CREATE TABLE `product_stock` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  `product_id` varchar(10) DEFAULT NULL COMMENT '產品ID',
  `channel_type` int(11) DEFAULT NULL COMMENT '渠道類型',
  `branch` varchar(10) DEFAULT NULL COMMENT '子產品',
  `stock` int(11) DEFAULT NULL COMMENT '庫存',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=47 DEFAULT CHARSET=utf8;

/*Data for the table `product_stock` */

insert  into `product_stock`
(`id`,`product_id`,`channel_type`,`branch`,`stock`)
values (1,'P002',1,'豪華房',23),
(2,'P001',1,'高級標間',45),
(3,'P003',1,'高級標間',33),
(4,'P004',1,'經典房',65),
(5,'P003',1,'小型套房',45),
(6,'P002',2,'高級標間',331),
(7,'P005',2,'小型套房',223),
(8,'P001',1,'豪華房',99),
(9,'P002',3,'高級標間',65),
(10,'P003',2,'經典房',45),
(11,'P004',3,'標准雙床房',67),
(12,'P005',2,'小型套房',34),
(13,'P001',1,'高級標間',43),
(14,'P002',3,'豪華房',56),
(15,'P001',3,'高級標間',77),
(16,'P005',2,'經典房',67),
(17,'P003',2,'高級標間',98),
(18,'P002',3,'經典房',23),
(19,'P004',2,'經典房',76),
(20,'P002',1,'小型套房',123);

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34

通過分組聚合GROUP_CONCAT實現

SELECT
  product_id,
  branch,
  GROUP_CONCAT(t.stock ORDER BY t.stock DESC ) stocks
FROM (SELECT *
      FROM product_stock) t
GROUP BY product_id,branch

    1
    2
    3
    4
    5
    6
    7

查詢結果:
product_id    branch    stocks
P001    豪華房    99
P001    高級標間    77,45,43
P002    小型套房    123
P002    經典房    23
P002    豪華房    56,23
P002    高級標間    331,65
P003    小型套房    45
P003    經典房    45
P003    高級標間    98,33
P004    標准雙床房    67
P004    經典房    76,65
P005    小型套房    223,34
P005    經典房    67

這也許並不是我們想要的結果,我們只要stocks中的最大值就可以,那么我們只要用SUBSTRING_INDEX函數截取一下就可以:

SELECT
  product_id,
  branch,
  SUBSTRING_INDEX(GROUP_CONCAT(t.stock ORDER BY t.stock DESC ),',',1) stock
FROM (SELECT *
      FROM product_stock) t
GROUP BY product_id,branch

    1
    2
    3
    4
    5
    6
    7

查詢結果:
product_id    branch    stock
P001    豪華房    99
P001    高級標間    77
P002    小型套房    123
P002    經典房    23
P002    豪華房    56
P002    高級標間    331
P003    小型套房    45
P003    經典房    45
P003    高級標間    98
P004    標准雙床房    67
P004    經典房    76
P005    小型套房    223
P005    經典房    67
通過關聯查詢及COUNT函數實現

SELECT *
FROM (SELECT
        t.product_id,
        t.branch,
        t.stock,
        COUNT(*)     AS rank
      FROM product_stock t
        LEFT JOIN product_stock r
          ON t.product_id = r.product_id
            AND t.branch = r.branch
            AND t.stock <= r.stock
      GROUP BY t.id) s
WHERE s.rank = 1

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

查詢結果:
product_id    branch    stock    rank
P003    小型套房    45    1
P002    高級標間    331    1
P005    小型套房    223    1
P001    豪華房    99    1
P003    經典房    45    1
P004    標准雙床房    67    1
P002    豪華房    56    1
P001    高級標間    77    1
P005    經典房    67    1
P003    高級標間    98    1
P002    經典房    23    1
P004    經典房    76    1
P002    小型套房    123    1

通過關聯表本身,聯接條件中:t.stock <= r.stock,當t.stock = r.stock時,COUNT出來的數量是1,當t.stock < r.stock時,COUNT出來的數量2,3,4…由此可以給所有的數據根據stock字段做一個排序,而這個排序中所有為1的,就是我們所需求的數據,然后通過按id分組,得到結果。通過這種方式,也可以實現上面的需求。
————————————————
版權聲明:本文為CSDN博主「MrCao傑羅爾德」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/m0_37797991/article/details/80511855


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM