【问题标题】:SQL - Find max based on contents of another columnSQL - 根据另一列的内容查找最大值
【发布时间】:2012-05-06 17:26:22
【问题描述】:

必须有一种优雅的方式来做到这一点,但我被困住了。

我有一张包含化学数据的表格。有些值“等于”,有些“小于”报告值,这在相邻列中表示(带有“

我需要一个查询,该查询将返回与“=”相关联的每个元素的最大值(如果有),即使有与“

看起来很简单,但我就是搞不定。一如既往,我们非常感谢任何帮助。

------------------------------
-- Table structure for `chem`
------------------------------
DROP TABLE IF EXISTS `chem`;
CREATE TABLE `chem` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`Element` varchar(12) DEFAULT NULL,
`Value` tinyint(4) DEFAULT NULL,
`Qualifier` varchar(2) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=latin1;

-- ----------------------------
-- Records of chem
-- ----------------------------
INSERT INTO `Chem` VALUES ('2', 'Copper', '1', '=');
INSERT INTO `Chem` VALUES ('3', 'Copper', '1', '=');
INSERT INTO `Chem` VALUES ('4', 'Copper', '3', '=');
INSERT INTO `Chem` VALUES ('5', 'Copper', '4', '=');
INSERT INTO `Chem` VALUES ('6', 'Copper', '5', '=');
INSERT INTO `Chem` VALUES ('7', 'Copper', '6', '=');
INSERT INTO `Chem` VALUES ('8', 'Copper', '7', '=');
INSERT INTO `Chem` VALUES ('9', 'Copper', '8', '=');
INSERT INTO `Chem` VALUES ('10', 'Copper', '9', '=');
INSERT INTO `Chem` VALUES ('11', 'Copper', '10', '=');
INSERT INTO `Chem` VALUES ('12', 'Nickel', '1', '<');
INSERT INTO `Chem` VALUES ('13', 'Nickel', '2', '<');
INSERT INTO `Chem` VALUES ('14', 'Nickel', '3', '=');
INSERT INTO `Chem` VALUES ('15', 'Nickel', '4', '<');
INSERT INTO `Chem` VALUES ('16', 'Nickel', '5', '=');
INSERT INTO `Chem` VALUES ('17', 'Nickel', '6', '=');
INSERT INTO `Chem` VALUES ('18', 'Nickel', '7', '=');
INSERT INTO `Chem` VALUES ('19', 'Nickel', '8', '=');
INSERT INTO `Chem` VALUES ('20', 'Nickel', '9', '=');
INSERT INTO `Chem` VALUES ('21', 'Nickel', '10', '=');
INSERT INTO `Chem` VALUES ('22', 'Lead', '1', '<');
INSERT INTO `Chem` VALUES ('23', 'Lead', '2', '<');
INSERT INTO `Chem` VALUES ('24', 'Lead', '3', '=');
INSERT INTO `Chem` VALUES ('25', 'Lead', '4', '=');
INSERT INTO `Chem` VALUES ('26', 'Lead', '5', '=');
INSERT INTO `Chem` VALUES ('27', 'Lead', '6', '<');
INSERT INTO `Chem` VALUES ('28', 'Lead', '7', '=');
INSERT INTO `Chem` VALUES ('29', 'Lead', '8', '=');
INSERT INTO `Chem` VALUES ('30', 'Lead', '9', '=');
INSERT INTO `Chem` VALUES ('31', 'Lead', '10', '<');

【问题讨论】:

  • 您的测试数据缺少一个案例——一个包含所有“

标签: mysql sql function aggregate


【解决方案1】:

另一种解决方案是在 MAX 语句中使用 CASE 语句。这是在 SQL 中执行 SUMIF、COUNTIF 等类型语句的常用方法。这个技巧将 will 扩展到您想要过滤正在聚合的值的许多情况。

此解决方案非常有效,因为它只需要对数据集进行一次扫描,这与具有连接或联合的解决方案不同。

例如:

SELECT Element
       ,COALESCE(MAX(CASE WHEN Qualifier = '=' THEN Value ELSE NULL END), MAX(CASE WHEN Qualifier = '<' THEN Value ELSE NULL END))
FROM chem
GROUP BY Element

【讨论】:

  • +1 :将其更改为 COALESCE(MAX(), MAX()) ,您将得到 OP 想要的内容。此外,这是在对数据的单次扫描中完成的(此处其他需要两次扫描),并且没有 JOIN、UNION 等。
  • 是的,添加了 COALESCE 这是最好的解决方案。
  • 太棒了。稍作调整,它就像一个魅力。谢谢你教我一个新的有用的功能。
【解决方案2】:
 SELECT Element, MAX(Value) FROM Chem WHERE Qualifier = '=' GROUP BY Element
 UNION ALL
 SELECT Element, MAX(Value) FROM Chem C1 WHERE
   NOT EXISTS (SELECT * FROM Chem WHERE Element = C1.Element AND Qualifier = '=')
   GROUP BY Element

这会执行两个查询并将结果组合成一个结果集。

第一个查询找到每个具有“=”限定符的元素的最大值。第二个查询处理另一种情况,其中没有“=”限定符,并返回这组元素中每个元素的最大值。

【讨论】:

  • 我认为这不适用于同一元素的记录同时具有 '=' 和非'=' 限定符的情况。在这种情况下,我希望有两行。
  • 为什么会这样?第一个查询仅包含元素 with "=" 限定符,第二个查询仅包含元素 without "=" 限定符。查看示例数据,第二个查询不会将任何记录添加到结果集中。第二个查询确实处理了丢失的测试用例,其中所有记录都有“
  • NOT EXISTS 可能会非常慢,尤其是对于子查询。我相信 LEFT JOIN 会快很多。
  • 越快越好(像这样的相关 NOT EXISTS 确实会很慢),但前提是你得到正确的结果。我不知道您如何仅使用 JOIN 来解决此问题。
  • @Larry Lustig - 因为 GROUP BY 应用于 UNION ALL 之前的每个查询。如果您同时拥有 qualifier='=' 和 qualifier'=' 行,您将获得两个 GROUP BY 结果馈送到 UNION ALL 中,从而为给定元素产生两个结果。我的逻辑有缺陷吗?
猜你喜欢
  • 2021-07-25
  • 1970-01-01
  • 1970-01-01
  • 2021-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-26
  • 1970-01-01
相关资源
最近更新 更多