在mysql中获得GROUP BY的最高计算分数

在mysql中获得GROUP BY的最高计算分数,mysql,group-by,groupwise-maximum,Mysql,Group By,Groupwise Maximum,我正试图根据客户和/或其客户群检索每种数量的产品的最合适价格。为此,我使用了一个基于权重的系统:匹配的客户组比匹配的客户更重要,因此如果两行发生冲突,我们应该得到对应于客户组id的行 下面是一个例子: Customer n°1 is part of Customer group n°2 Product prices: A - 90€ for customer n°1 (when buying at least 2 of the same product) B - 80€ for custom

我正试图根据客户和/或其客户群检索每种数量的产品的最合适价格。为此,我使用了一个基于权重的系统:匹配的客户组比匹配的客户更重要,因此如果两行发生冲突,我们应该得到对应于客户组id的行

下面是一个例子:

Customer n°1 is part of Customer group n°2
Product prices:
 A - 90€ for customer n°1 (when buying at least 2 of the same product)
 B - 80€ for customer group n°2 (when buying at least 2 of the same product)
So the price shown to the customer n°1 should be 80€
他是我的问题:

SELECT 
    MAX(IF(t.customer_id = 1, 10, 0) + IF(t.customer_group_id = 1, 100, 0)) as score, 
    t.*
FROM tierprice t
WHERE t.product_variant_id = 110 
    AND (t.customer_id = 1 OR t.customer_id IS NULL) 
    AND (t.customer_group_id = 1 OR t.customer_group_id IS NULL)
GROUP BY t.product_variant_id, t.qty
我遇到的问题是,这里的结果行显示了正确的分数:100,但给定分数的行不正确。我猜这与SELECT和GROUP BY中的最大值有关,但我不知道如何将分数分配给行,然后取最高值

这是一把小提琴:

CREATE TABLE `tierprice` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `product_variant_id` int(11) DEFAULT NULL,
  `customer_group_id` int(11) DEFAULT NULL,
  `price` int(11) NOT NULL,
  `qty` int(11) NOT NULL,
  `customer_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `no_duplicate_prices` (`qty`,`product_variant_id`,`customer_group_id`),
  KEY `IDX_BA5254F8A80EF684` (`product_variant_id`),
  KEY `IDX_BA5254F8D2919A68` (`customer_group_id`),
  KEY `IDX_BA5254F89395C3F3` (`customer_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

INSERT INTO `tierprice` (`id`, `product_variant_id`, `customer_group_id`, `price`, `qty`, `customer_id`)
VALUES
    (1, 110, NULL, 8000, 2, 1),
    (2, 110, 1, 7000, 2, NULL),
    (3, 110, 1, 6000, 5, NULL),
    (4, 110, NULL, 5000, 5, 1),
    (5, 111, 1, 8000, 2, NULL),
    (6, 111, NULL, 6000, 2, 1),
    (7, 111, 1, 7000, 6, NULL),
    (8, 111, NULL, 5000, 6, 1);
结果中应该显示的价格ID应该是ID 2和ID 3


感谢您的帮助。

您的查询可以返回的唯一有效列是产品变量id、数量(您在GROUP BY子句中使用)和聚合列分数。 由于t.*的原因,您将获得表中的所有列,但对于其他列,所选的值是不确定的,如中所述。 您可以做的是将查询连接到表,如下所示:

SELECT t.*
FROM tierprice t
INNER JOIN (
  SELECT product_variant_id, qty, 
         MAX(IF(customer_id = 1, 10, 0) + IF(customer_group_id = 1, 100, 0)) as score
  FROM tierprice 
  WHERE product_variant_id = 110 
    AND (customer_id = 1 OR customer_id IS NULL) 
    AND (customer_group_id = 1 OR customer_group_id IS NULL)
  GROUP BY product_variant_id, qty
) g ON g.product_variant_id = t.product_variant_id 
   AND g.qty = t.qty
   AND g.score = IF(t.customer_id = 1, 10, 0) + IF(t.customer_group_id = 1, 100, 0)
WHERE (t.customer_id = 1 OR t.customer_id IS NULL) 
  AND (t.customer_group_id = 1 OR t.customer_group_id IS NULL)
看。 结果:


查询可以返回的唯一有效列是产品变量id、数量(在GROUP BY子句中使用)和聚合列分数。 由于t.*的原因,您将获得表中的所有列,但对于其他列,所选的值是不确定的,如中所述。 您可以做的是将查询连接到表,如下所示:

SELECT t.*
FROM tierprice t
INNER JOIN (
  SELECT product_variant_id, qty, 
         MAX(IF(customer_id = 1, 10, 0) + IF(customer_group_id = 1, 100, 0)) as score
  FROM tierprice 
  WHERE product_variant_id = 110 
    AND (customer_id = 1 OR customer_id IS NULL) 
    AND (customer_group_id = 1 OR customer_group_id IS NULL)
  GROUP BY product_variant_id, qty
) g ON g.product_variant_id = t.product_variant_id 
   AND g.qty = t.qty
   AND g.score = IF(t.customer_id = 1, 10, 0) + IF(t.customer_group_id = 1, 100, 0)
WHERE (t.customer_id = 1 OR t.customer_id IS NULL) 
  AND (t.customer_group_id = 1 OR t.customer_group_id IS NULL)
看。 结果:


从SQL标准的角度来看,提供的查询不是有效的查询:

SELECT 
    MAX(IF(t.customer_id = 1, 10, 0) + IF(t.customer_group_id = 1, 100, 0)) as score, 
    t.*
FROM tierprice t
WHERE t.product_variant_id = 110 
    AND (t.customer_id = 1 OR t.customer_id IS NULL) 
    AND (t.customer_group_id = 1 OR t.customer_group_id IS NULL)
GROUP BY t.product_variant_id, t.qty;
SELECT列表的表达式2不在GROUP BY子句中,并且包含未聚合的列“t.id”,该列在功能上不依赖于GROUP BY子句中的列;这与sql\u mode=only\u full\u group\u by不兼容

相关的:

可以使用窗口函数MSYSQL 8.0及更高版本重写:

WITH cte AS (
 SELECT t.*, ROW_NUMBER() OVER(PARTITION BY product_variant_id, qty 
             ORDER BY IF(t.customer_id=1,10,0)+IF(t.customer_group_id=1,100,0) DESC) AS rn
 FROM tierprice t
 WHERE t.product_variant_id = 110 
     AND (t.customer_id = 1 OR t.customer_id IS NULL) 
     AND (t.customer_group_id = 1 OR t.customer_group_id IS NULL)
)
SELECT *
FROM cte
WHERE rn = 1;

从SQL标准的角度来看,提供的查询不是有效的查询:

SELECT 
    MAX(IF(t.customer_id = 1, 10, 0) + IF(t.customer_group_id = 1, 100, 0)) as score, 
    t.*
FROM tierprice t
WHERE t.product_variant_id = 110 
    AND (t.customer_id = 1 OR t.customer_id IS NULL) 
    AND (t.customer_group_id = 1 OR t.customer_group_id IS NULL)
GROUP BY t.product_variant_id, t.qty;
SELECT列表的表达式2不在GROUP BY子句中,并且包含未聚合的列“t.id”,该列在功能上不依赖于GROUP BY子句中的列;这与sql\u mode=only\u full\u group\u by不兼容

相关的:

可以使用窗口函数MSYSQL 8.0及更高版本重写:

WITH cte AS (
 SELECT t.*, ROW_NUMBER() OVER(PARTITION BY product_variant_id, qty 
             ORDER BY IF(t.customer_id=1,10,0)+IF(t.customer_group_id=1,100,0) DESC) AS rn
 FROM tierprice t
 WHERE t.product_variant_id = 110 
     AND (t.customer_id = 1 OR t.customer_id IS NULL) 
     AND (t.customer_group_id = 1 OR t.customer_group_id IS NULL)
)
SELECT *
FROM cte
WHERE rn = 1;

请参阅我添加的标签。您提到了与客户关联的组。您能否提供显示其ID和所属GroupID的示例客户表?在这个示例中,您的所有数据都只涉及客户1和组1,这与所有数据的真实场景相去甚远。您不希望有一个硬编码的解决方案,其中嵌入了特定的ID。您的组定价也有数量价格断点2和5,并且也不希望在那里固定。另外,实际订购的数量将从哪里来,而不是固定的。。。订单详情?显示带有客户、产品、订购数量的source To orderDetail表。请参阅我添加的标记。您提到了与客户关联的组。您能否提供显示其ID和所属GroupID的示例客户表?在这个示例中,您的所有数据都只涉及客户1和组1,这与所有数据的真实场景相去甚远。您不希望有一个硬编码的解决方案,其中嵌入了特定的ID。您的组定价也有数量价格断点2和5,并且也不希望在那里固定。另外,实际订购的数量将从哪里来,而不是固定的。。。订单详情?显示带有客户、产品、订购数量的source To orderDetail表。