如何解决 sql 记录分组问题?
How can I solve sql record grouping problem?
我正在尝试通过使用按功能分组来找到 return 结果的方法。
是否可以通过忽略NULL字段来进行分组。这样它就不会将 NULL 组合在一起,因为我仍然需要指定字段为 NULL 的所有行。
我的记录示例
表
id
status
mode
update_date
1
null
0
13:46
1
null
1
12:22
1
1
null
15:00
1
0
null
15:55
我想用非空列对最后的记录进行分组。
我尝试了这个查询,但没有成功:
SELECT id, status, mode, update_date FROM TABLEX ORDER BY update_date GROUP BY id
我想得到这个结果:
id
status
mode
update_date
1
0
0
15:55
我该如何解决这种情况。
备注:
- 这是 Oracle 18c 上的 运行。
- 一定有更好的方法....而且这还没有针对我能想到的所有边缘情况进行测试...但它似乎有效....
演示:https://dbfiddle.uk/?rdbms=oracle_18&fiddle=be87b5778616a4732db3a3c4787804e0
WITH CTE AS (SELECT 1 ID, null STATUS,0 "MODE", '13:46' UPDATE_DATE from dual UNION ALL
SELECT 1,null,1,'12:22' from dual UNION ALL
SELECT 1,1,null,'15:00' from dual UNION ALL
SELECT 1,0,null,'15:55' from dual)
SELECT A.ID, Z.Status, Y."MODE", max(A.Update_Date) UD
FROM CTE A
CROSS APPLY (SELECT B.Status FROM CTE B WHERE B.ID = A.ID and B.Status is not null ORDER BY UPDATE_DATE DESC FETCH FIRST 1 ROW ONLY) Z
CROSS APPLY (SELECT B."MODE" FROM CTE B WHERE B.ID = A.ID and B."MODE" is not null ORDER BY UPDATE_DATE DESC FETCH FIRST 1 ROW ONLY) Y
GROUP BY ID, Z.Status, Y."MODE"
+----+--------+------+-------+
| ID | STATUS | MODE | UD |
+----+--------+------+-------+
| 1 | 0 | 0 | 15:55 |
+----+--------+------+-------+
- 只要时间是 24 小时格式,我就不会为更新日期进行数据类型转换,结果是相同的,所以我没有花时间。
- 所以cross apply是运行主table中的每一行内联查询一次,并按照非空值的规则获取状态或模式,并且必须具有最高Update_Date.我认为
First_Value
分析会起作用;但我无法让它工作...(虽然我当时使用的是 11)
- 因为它将 return 一个 ID 中所有行的相同值,按它分组允许我们合并回 1 条记录。
- first_value 可能适用于 18 岁以上我没有在那里尝试过...
更多测试:https://dbfiddle.uk/?rdbms=oracle_18&fiddle=705747c5b5f0e8414a2561fa82842fb7
我正在尝试通过使用按功能分组来找到 return 结果的方法。
是否可以通过忽略NULL字段来进行分组。这样它就不会将 NULL 组合在一起,因为我仍然需要指定字段为 NULL 的所有行。
我的记录示例 表
id | status | mode | update_date |
---|---|---|---|
1 | null | 0 | 13:46 |
1 | null | 1 | 12:22 |
1 | 1 | null | 15:00 |
1 | 0 | null | 15:55 |
我想用非空列对最后的记录进行分组。
我尝试了这个查询,但没有成功:
SELECT id, status, mode, update_date FROM TABLEX ORDER BY update_date GROUP BY id
我想得到这个结果:
id | status | mode | update_date |
---|---|---|---|
1 | 0 | 0 | 15:55 |
我该如何解决这种情况。
备注:
- 这是 Oracle 18c 上的 运行。
- 一定有更好的方法....而且这还没有针对我能想到的所有边缘情况进行测试...但它似乎有效....
演示:https://dbfiddle.uk/?rdbms=oracle_18&fiddle=be87b5778616a4732db3a3c4787804e0
WITH CTE AS (SELECT 1 ID, null STATUS,0 "MODE", '13:46' UPDATE_DATE from dual UNION ALL
SELECT 1,null,1,'12:22' from dual UNION ALL
SELECT 1,1,null,'15:00' from dual UNION ALL
SELECT 1,0,null,'15:55' from dual)
SELECT A.ID, Z.Status, Y."MODE", max(A.Update_Date) UD
FROM CTE A
CROSS APPLY (SELECT B.Status FROM CTE B WHERE B.ID = A.ID and B.Status is not null ORDER BY UPDATE_DATE DESC FETCH FIRST 1 ROW ONLY) Z
CROSS APPLY (SELECT B."MODE" FROM CTE B WHERE B.ID = A.ID and B."MODE" is not null ORDER BY UPDATE_DATE DESC FETCH FIRST 1 ROW ONLY) Y
GROUP BY ID, Z.Status, Y."MODE"
+----+--------+------+-------+
| ID | STATUS | MODE | UD |
+----+--------+------+-------+
| 1 | 0 | 0 | 15:55 |
+----+--------+------+-------+
- 只要时间是 24 小时格式,我就不会为更新日期进行数据类型转换,结果是相同的,所以我没有花时间。
- 所以cross apply是运行主table中的每一行内联查询一次,并按照非空值的规则获取状态或模式,并且必须具有最高Update_Date.我认为
First_Value
分析会起作用;但我无法让它工作...(虽然我当时使用的是 11) - 因为它将 return 一个 ID 中所有行的相同值,按它分组允许我们合并回 1 条记录。
- first_value 可能适用于 18 岁以上我没有在那里尝试过...
更多测试:https://dbfiddle.uk/?rdbms=oracle_18&fiddle=705747c5b5f0e8414a2561fa82842fb7