SQL - 同一列上的两个 SUMS 需要互斥
SQL - Two SUMS on the same column need to be mutually exclusive
我正在尝试在 MySQL Workbench 中编写一个 SQL 查询,它将 return 向我显示我移动到特定状态的记录总和,仅考虑特定记录的最新时间戳。我还需要在 没有 子查询(或嵌套 select)的情况下执行此操作。
鉴于以下 table,我想知道 ID 为 1 的用户将两条记录移动到 ID 为 2[=39= 的状态].如果同一条记录被移动到两个不同的状态 ID,我不需要包括在我的计数中,但只计算最新的状态 ID。
Table
user_id
acted_on_record_id
moved_to_status_id
timestamp
1
1234
2
2022-01-01 19:39:37
1
1234
3
2022-01-02 19:39:37
1
1234
2
2022-01-03 19:39:37
1
5678
2
2022-01-03 19:39:37
这是我目前的查询:
SELECT t1.user_id, t1.acted_on_record_id,
SUM(DISTINCT IF(t1.moved_to_status_id = 3, 1, 0)) AS pending,
SUM(DISTINCT IF(t1.moved_to_status_id = 2, 1, 0)) AS open,
MAX(t1.timestamp) as timestamp
FROM table1 t1
GROUP BY t1.user_id, t1.acted_on_record_id
这是我想要的结果:
user_id
acted_on_record_id
pending
open
timestamp
1
1234
0
1
2022-01-03 19:39:37
1
5678
0
1
2022-01-03 19:39:37
但是,我的查询给出了这个结果:
user_id
acted_on_record_id
pending
open
timestamp
1
1234
1
1
2022-01-03 19:39:37
1
5678
0
1
2022-01-03 19:39:37
它在 pending 列和 open 列中显示 1,因为 SUM IF 聚合在 acted_on_record_id 上不互斥或不同。有没有办法让这两个聚合相互了解,并且只对具有更大时间戳的聚合求和而不使用子查询(嵌套 select)?
我最终通过扩展这里的解决方案弄明白了:Retrieving the last record in each group - MySQL
我使用 LEFT JOIN 将 table 与自身进行比较。此查询在 1.095 秒内返回,而我之前使用子查询的解决方案(未发布)在 15.268 秒内返回。
SELECT t1.user_id, t1.acted_on_record_id,
SUM(IF(t1.moved_to_status_id = 3, 1, 0)) AS pending,
SUM(IF(t1.moved_to_status_id = 2, 1, 0)) AS open
MAX(t1.timestamp) as timestamp
FROM table1 t1 LEFT JOIN table1 t2
ON (t1.acted_on_record_id = t2.acted_on_record_id AND t1.user_id = t2.user_id AND t1.id < t2.id)
WHERE t2.user_id IS NULL
group by t1.user_id, t1.acted_on_record_id, t1.moved_to_status_id
我正在尝试在 MySQL Workbench 中编写一个 SQL 查询,它将 return 向我显示我移动到特定状态的记录总和,仅考虑特定记录的最新时间戳。我还需要在 没有 子查询(或嵌套 select)的情况下执行此操作。
鉴于以下 table,我想知道 ID 为 1 的用户将两条记录移动到 ID 为 2[=39= 的状态].如果同一条记录被移动到两个不同的状态 ID,我不需要包括在我的计数中,但只计算最新的状态 ID。
Table
user_id | acted_on_record_id | moved_to_status_id | timestamp |
---|---|---|---|
1 | 1234 | 2 | 2022-01-01 19:39:37 |
1 | 1234 | 3 | 2022-01-02 19:39:37 |
1 | 1234 | 2 | 2022-01-03 19:39:37 |
1 | 5678 | 2 | 2022-01-03 19:39:37 |
这是我目前的查询:
SELECT t1.user_id, t1.acted_on_record_id,
SUM(DISTINCT IF(t1.moved_to_status_id = 3, 1, 0)) AS pending,
SUM(DISTINCT IF(t1.moved_to_status_id = 2, 1, 0)) AS open,
MAX(t1.timestamp) as timestamp
FROM table1 t1
GROUP BY t1.user_id, t1.acted_on_record_id
这是我想要的结果:
user_id | acted_on_record_id | pending | open | timestamp |
---|---|---|---|---|
1 | 1234 | 0 | 1 | 2022-01-03 19:39:37 |
1 | 5678 | 0 | 1 | 2022-01-03 19:39:37 |
但是,我的查询给出了这个结果:
user_id | acted_on_record_id | pending | open | timestamp |
---|---|---|---|---|
1 | 1234 | 1 | 1 | 2022-01-03 19:39:37 |
1 | 5678 | 0 | 1 | 2022-01-03 19:39:37 |
它在 pending 列和 open 列中显示 1,因为 SUM IF 聚合在 acted_on_record_id 上不互斥或不同。有没有办法让这两个聚合相互了解,并且只对具有更大时间戳的聚合求和而不使用子查询(嵌套 select)?
我最终通过扩展这里的解决方案弄明白了:Retrieving the last record in each group - MySQL
我使用 LEFT JOIN 将 table 与自身进行比较。此查询在 1.095 秒内返回,而我之前使用子查询的解决方案(未发布)在 15.268 秒内返回。
SELECT t1.user_id, t1.acted_on_record_id,
SUM(IF(t1.moved_to_status_id = 3, 1, 0)) AS pending,
SUM(IF(t1.moved_to_status_id = 2, 1, 0)) AS open
MAX(t1.timestamp) as timestamp
FROM table1 t1 LEFT JOIN table1 t2
ON (t1.acted_on_record_id = t2.acted_on_record_id AND t1.user_id = t2.user_id AND t1.id < t2.id)
WHERE t2.user_id IS NULL
group by t1.user_id, t1.acted_on_record_id, t1.moved_to_status_id