MySQL:复杂的GROUP BY查询

时间:2018-09-24 03:15:44

标签: mysql group-by

我们正在尝试找到一个问题的解决方案,该问题我已经能够通过说明性表格进行复制。这是说明性表格的创建方式:

create table illustrativeTable
(
  id INT UNSIGNED NOT NULL AUTO_INCREMENT,
  label VARCHAR(4),
  reportingDate DATE,
  attr_1 INT,
  attr_2 INT,
  attr_3 INT,

  PRIMARY KEY(id)
);

我已将说明性表格填充如下:

INSERT INTO illustrativeTable(label, reportingDate, attr_1, attr_2, attr_3) VALUES('A', '2018-01-01', '1', '3', '100'),
('A', '2018-01-05', '2', '4', '125'), ('A', '2018-01-07', '2', '5', '125'),
('A', '2018-01-08', '3', '6', '150'), ('A', '2018-01-11', '4', '7', NULL),
('B', '2018-01-02', '1', '3', '50'), ('B', '2018-01-05', '2', '5', '75'),
('B', '2018-01-06', '3', '6', '200'), ('B', '2018-01-16', '3', '5', '200'),
('C', '2018-01-05', '6', '9', '175'),('C', '2018-01-08', '7', '9', '225'),
('D', '2018-01-01', '2', '5', '55'), ('D', '2018-01-15', '3', '6', 85),
('D', '2018-01-21', '4', '7', '75'), ('E', '2018-01-25', '2', '4', '65'),
('E', '2018-01-28', '2', '5', NULL);

查询

SELECT * FROM illustrativeTable;

产生以下输出:

+----+-------+---------------+--------+--------+--------+
| id | label | reportingDate | attr_1 | attr_2 | attr_3 |
+----+-------+---------------+--------+--------+--------+
|  1 | A     | 2018-01-01    |      1 |      3 |    100 |
|  2 | A     | 2018-01-05    |      2 |      4 |    125 |
|  3 | A     | 2018-01-07    |      2 |      5 |    125 |
|  4 | A     | 2018-01-08    |      3 |      6 |    150 |
|  5 | A     | 2018-01-11    |      4 |      7 |   NULL |
|  6 | B     | 2018-01-02    |      1 |      3 |     50 |
|  7 | B     | 2018-01-05    |      2 |      5 |     75 |
|  8 | B     | 2018-01-06    |      3 |      6 |    200 |
|  9 | B     | 2018-01-16    |      3 |      5 |    200 |
| 10 | C     | 2018-01-05    |      6 |      9 |    175 |
| 11 | C     | 2018-01-08    |      7 |      9 |    225 |
| 12 | D     | 2018-01-01    |      2 |      5 |     55 |
| 13 | D     | 2018-01-15    |      3 |      6 |     85 |
| 14 | D     | 2018-01-21    |      4 |      7 |     75 |
| 15 | E     | 2018-01-25    |      2 |      4 |     65 |
| 16 | E     | 2018-01-28    |      2 |      5 |   NULL |
+----+-------+---------------+--------+--------+--------+

我们的问题是,我们要从选定的元组中检索标签,reportDate和attr_3, ,但有以下限制:
1)attr_2-attr_1 = 3
2)attr_3不为空
3)如果有多个匹配,则选择 reportingDate的最高值的值

简单查询:

SELECT label, reportingDate, attr_3 FROM illustrativeTable
WHERE label IN ('A', 'B', 'C', 'E') AND (attr_2-attr_1=3)
AND attr_3 IS NOT NULL GROUP BY label;

产生以下结果:

+-------+---------------+--------+
| label | reportingDate | attr_3 |
+-------+---------------+--------+
| A     | 2018-01-07    |    125 |
| B     | 2018-01-05    |     75 |
| C     | 2018-01-05    |    175 |
+-------+---------------+--------+

此结果的问题是,对于标签“ A”,满足所有约束的最高报告日期是2018-01-08。同样,对于标签“ B”,满足所有限制的最高报告日期是2018年1月6日。

我们想调整查询,以便输出看起来如下:

+-------+---------------+--------+
| label | reportingDate | attr_3 |
+-------+---------------+--------+
| A     | 2018-01-08    |    150 |
| B     | 2018-01-06    |    200 |
| C     | 2018-01-05    |    175 |
+-------+---------------+--------+

我确实尝试了一些想法 https://paulund.co.uk/get-last-record-in-each-mysql-group   但是我找不到想要的结果。

1 个答案:

答案 0 :(得分:2)

要获得最高reportingDate的输出,只需要将其作为约束添加到查询中。请注意,除非给定的reportingDate具有多个数据值,否则不需要GROUP BY子句:

SELECT label, reportingDate, attr_3 
FROM illustrativeTable it1
WHERE label IN ('A', 'B', 'C', 'E') AND 
      (attr_2-attr_1=3) AND
      attr_3 IS NOT NULL AND
      reportingDate = (SELECT MAX(reportingDate) 
                       FROM illustrativeTable 
                       WHERE label = it1.label AND 
                             attr_2-attr_1=3 AND 
                             attr_3 IS NOT NULL)

输出:

label   reportingDate   attr_3  
A       2018-01-08      150
B       2018-01-06      200
C       2018-01-05      175

如果给定的reportingDate确实有多个值,则需要GROUP BY label,并且还必须决定是否要使用attr_3的最小值或最大值,在这种情况下,您可以将查询中的attr_3分别更改为MIN(attr_3)MAX(attr_3)

更新

基于OP在下面的注释中指定的其他条件,这可能是获得所需结果的最有效查询。它将初始表的子选择(应用了非聚集条件)连接到另外两个表,这些表给出了reportingDate的最大label和{{1}的最大值{1}}和attr2,分别使用reportingDate条件过滤掉与labelJOIN不匹配的所有条目。

MAX(reportingDate)

对于示例数据,输出保持不变,但是我已经使用触发rextester上的MAX(attr_2)条件的数据对其进行了测试。