mysql - 有没有办法根据另一列的值更新列值?
问题描述
我的 SQL 任务的第 1 部分涉及重组数据。我的任务要点如下:基于 event_type,如果它是“开始”,我试图使用那个“时间”来找到它的停止时间(在另一行)并将其添加到列(event_end)与开始时间在同一行,以便事件的所有数据很好地放在一行中。
pID customerID locationID event_type time event_end (new row)
1 1 a begin 12.45
2 2 a begin 11.10
3 1 a stop 1.30
4 2 b begin 9.45
5 3 b stop 8.78
我想添加另一列(event_end),并且让 event_end = event_start 的最小值 IF event_start = 'stop'、IF locationID = locationID 和 IF customerID = customerID。最后一步是删除所有 event_start 'begin' 行。
我已经尝试过 UPDATE SET WHERE 序列和一点点 CASE,但我的问题是,如果没有像 VBA 这样的循环,我无法理解如何执行此操作。以下是我最好的尝试:
UPDATE table
SET event_end = MIN(time)
WHERE event_type = 'stop'
WHERE customerid = customerid
WHERE locationid = locationid
WHERE time > time
SELECT *
FROM table
我希望在一行中有一个包含所有事件数据的表,而不是分布在多行中。如果这是少数,我表示歉意,但提前表示感谢。谢谢
解决方案
问题陈述:
- 作为额外属性添加
event_end
到现有行,数据将基于customer_id, location_id
. - 我们将数据填充
event_end
到事件类型为的所有事件中begin
- 数据将从与 具有相同
customer_id, location_id
但事件类型的行中选取stop
。 - 最后,我们将删除所有类型为 的事件
stop
。
解决方案:考虑您的表名是customer_events
并且将使用self join
相同的概念。
首先,确定哪些记录需要更新。我们可以使用
SELECT
查询来识别此类记录。c1
表将表示具有begin
事件类型的行。c2
表将表示具有stop
事件类型的行。
SELECT *
FROM customer_events c1
LEFT JOIN customer_events c2 ON c1.customerID = c2.customerID AND c1.locationID = c2.locationID AND c1.event_type = 'begin' AND c2.event_type = 'stop'
WHERE c1.event_type = 'begin'; -- As we want to populate data in events with value as `begin`
- 编写查询以更新记录。
UPDATE customer_events c1
LEFT JOIN customer_events c2 ON c1.customerID = c2.customerID AND c1.locationID = c2.locationID AND c1.event_type = 'begin' AND c2.event_type = 'stop'
SET c1.event_end = c2.`time`
WHERE c1.event_type = 'begin';
现在,每个事件类型为 as 的记录
begin
在列中都有一个值,或者如果没有记录匹配为事件event_end
,它将为空。stop
对于事件类型为 as 的行
stop
,它们要么映射到事件类型为 as 的某些行,要么begin
未映射。在这两种情况下,我们都不想保留它们。删除事件类型为 的所有记录stop
。
DELETE FROM customer_events
WHERE event_type = 'stop';
DELETE
注意:除非您确定此解决方案对您有用,否则不要运行语句。
更新:我们可以begin & stop
为单个客户和位置记录多条事件记录。
Sample Input:
| pID | customerID* | *locationID* | *event_type* | *time* | *event_end* |
| 1 | 1 | a | begin | 02:45:00 | |
| 2 | 2 | a | begin | 03:10:00 | |
| 3 | 1 | b | begin | 04:30:00 | |
| 4 | 2 | b | begin | 05:45:00 | |
| 5 | 2 | a | stop | 06:49:59 | |
| 6 | 1 | a | begin | 07:38:00 | |
| 7 | 3 | b | begin | 08:57:19 | |
| 8 | 2 | b | stop | 09:57:43 | |
| 9 | 3 | b | stop | 10:58:03 | |
| 10 | 4 | a | begin | 11:58:34 | |
| 11 | 1 | a | stop | 12:09:36 | |
| 12 | 1 | b | stop | 13:09:50 | |
| 13 | 1 | a | stop | 14:10:02 | |
询问:
SELECT *
FROM (
SELECT
ce.*,
IF(@c_id <> ce.customerId OR @l_id <> ce.locationID, @rank:= 1, @rank:= @rank + 1 ) as rank,
@c_id:= ce.customerId,
@l_id:= ce.locationID
FROM customer_events ce,
(SELECT @c_id:= 0 c, @l_id:= '' l, @rank:= 0 r) AS t
WHERE event_type = 'begin'
ORDER BY customerId, locationID, `time`) AS c1
LEFT JOIN (
SELECT
ce.*,
IF(@c_id <> ce.customerId OR @l_id <> ce.locationID, @rank:= 1, @rank:= @rank + 1 ) as rank,
@c_id:= ce.customerId,
@l_id:= ce.locationID
FROM customer_events ce,
(SELECT @c_id:= 0 c, @l_id:= '' l, @rank:= 0 r) AS t
WHERE event_type = 'stop'
ORDER BY customerId, locationID, `time`
) AS c2 ON c1.customerID = c2.customerID AND c1.locationID = c2.locationID AND c1.rank = c2.rank;
Output:
| pId | customerID| locationId| event_type| Start_Time|End_Id| End_Time |
| 1 | 1 | a | begin | 02:45:00 | 11 | 12:09:36 |
| 6 | 1 | a | begin | 07:38:00 | 13 | 14:10:02 |
| 3 | 1 | b | begin | 04:30:00 | 12 | 13:09:50 |
| 2 | 2 | a | begin | 03:10:00 | 5 | 06:49:59 |
| 4 | 2 | b | begin | 05:45:00 | 8 | 09:57:43 |
| 7 | 3 | b | begin | 08:57:19 | 9 | 10:58:03 |
| 10 | 4 | a | begin | 11:58:34 | | |
更新语句:创建两列end_pID
并event_end
用于迁移。
UPDATE customer_events
INNER JOIN (
SELECT c1.pId, c2.pID End_Id, c2.time AS End_Time
FROM (
SELECT
ce.*,
IF(@c_id <> ce.customerId OR @l_id <> ce.locationID, @rank:= 1, @rank:= @rank + 1 ) as rank,
@c_id:= ce.customerId,
@l_id:= ce.locationID
FROM customer_events ce,
(SELECT @c_id:= 0 c, @l_id:= '' l, @rank:= 0 r) AS t
WHERE event_type = 'begin'
ORDER BY customerId, locationID, `time`) AS c1
LEFT JOIN (
SELECT
ce.*,
IF(@c_id <> ce.customerId OR @l_id <> ce.locationID, @rank:= 1, @rank:= @rank + 1 ) as rank,
@c_id:= ce.customerId,
@l_id:= ce.locationID
FROM customer_events ce,
(SELECT @c_id:= 0 c, @l_id:= '' l, @rank:= 0 r) AS t
WHERE event_type = 'stop'
ORDER BY customerId, locationID, `time`
) AS c2 ON c1.customerID = c2.customerID AND c1.locationID = c2.locationID AND c1.rank = c2.rank) AS tt ON customer_events.pID = tt.pId
SET customer_events.end_pID = t.End_Id, customer_events.event_end = t.End_Time;
最后,删除所有事件event_type = 'stop'
推荐阅读
- javascript - 使用 Azure JS SDK for Service Bus 时需要关闭连接吗?
- c++ - LNK1169 找到一个或多个多重定义的符号。我知道这可能被认为是重复的,但我找不到任何可以解决我的问题的东西
- r - 如何在 R 中的整个数据集中删除列中的重复值
- python - 当代码在循环上运行时,Python当前时间不会改变
- django - 我的查询返回一个 Id 而不是实际值
- amazon-web-services - 在 API 网关的 REST URI 中使用 base64 编码的路径参数
- json - Amchart 4 人口金字塔
- ios - DispatchQueue 和网络请求
- javascript - 在一种方法中动态创建剑道下拉菜单并在另一种方法中分配数据源
- java - 无法从数组中选择一个元素并将其分配给矩阵中的一个点