我的SQL任务的第1部分涉及重组数据。我的任务的基本内容如下:基于event_type,如果它是“ begin”,则尝试使用该“ time”来查找其停止时间(在另一行中)并将其添加到该列的“ 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_start ='stop',IF locationID = locationID和IF customerID = customerID的情况下,使event_end = event_start的最小值。最后一步是删除所有event_start“开始”行。
我已经尝试过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
我希望有一个表,其中所有事件数据都在一行中,而不是分布在多行中。如果这是少数,我表示歉意,但在此先感谢。 谢谢
答案 0 :(得分:1)
问题陈述:
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';
现在,每个事件类型为begin
的记录都在event_end
列中具有值,或者如果没有记录与stop
事件匹配则为空。
对于事件类型为stop
的行,它们被映射为事件类型为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'