MySQL获取查询中当前行的前后行
我在MySQL中有五个表,我正在从中生成一些报告。为了便于显示,我将稍微抽象表名。假设我使用的表如下所述:MySQL获取查询中当前行的前后行,mysql,sql,database,Mysql,Sql,Database,我在MySQL中有五个表,我正在从中生成一些报告。为了便于显示,我将稍微抽象表名。假设我使用的表如下所述: History (id, serial, date, time) : Stores historic data, this is the main column we query. Serial (id, serial) : Stores serial numbers used in th
History (id, serial, date, time) : Stores historic data, this is the main
column we query.
Serial (id, serial) : Stores serial numbers used in the next
3 tables.
Employee (id, serial_id, name)
Event (id, serial_id, name)
Location (id, serial_id, name)
编辑:重写整个问题,希望它更清晰、更容易理解
我需要查询事件,同样,如果在历史记录中直接在序列与事件匹配的行之前找到员工序列,则该员工将与该事件关联,同样,如果在序列与事件匹配的行之后直接在历史记录中找到位置,该位置将与该事件关联
样本数据:
History:
+------+------------+------------+----------+
| id | serial | date | time |
+------+------------+------------+----------+
| 1 | 00001234 | 2012-09-25 | 09:00:00 |
+------+------------+------------+----------+
| 2 | 00001235 | 2012-09-25 | 09:01:00 |
+------+------------+------------+----------+
| 3 | 00001236 | 2012-09-25 | 09:02:00 |
+------+------------+------------+----------+
| 4 | 00001235 | 2012-09-25 | 09:05:00 |
+------+------------+------------+----------+
| 5 | 00001236 | 2012-09-25 | 09:07:00 |
+------+------------+------------+----------+
| 6 | 00001235 | 2012-09-25 | 09:10:00 |
+------+------------+------------+----------+
| 7 | 00001235 | 2012-09-25 | 09:11:00 |
+------+------------+------------+----------+
| 8 | 00001235 | 2012-09-25 | 09:12:00 |
+------+------------+------------+----------+
| 9 | 00001236 | 2012-09-25 | 09:15:00 |
+------+------------+------------+----------+
| 10 | 00001234 | 2012-09-25 | 09:20:00 |
+------+------------+------------+----------+
| 11 | 00001236 | 2012-09-25 | 09:25:00 |
+------+------------+------------+----------+
Serial:
+----------+------------+
| id | serial |
+----------+------------+
| 1 | 00001234 |
+----------+------------+
| 2 | 00001235 |
+----------+------------+
| 3 | 00001236 |
+----------+------------+
Employee:
+----------+------------+-------------+
| id | serial_id | name |
+----------+------------+-------------+
| 1 | 1 | John Smith |
+----------+------------+-------------+
Event:
+----------+------------+-------------+
| id | serial_id | name |
+----------+------------+-------------+
| 1 | 2 | Event 1 |
+----------+------------+-------------+
Location:
+----------+------------+-------------+
| id | serial_id | name |
+----------+------------+-------------+
| 1 | 3 | Location 1 |
+----------+------------+-------------+
如果我使用以下查询执行正常的左连接查询(只是为了清楚显示结果的差异),结果将是:
SELECT
history.id,
history.serial,
history.date,
history.time,
employee.name as 'employee',
event.name as 'event',
location.name as 'location'
FROM history
LEFT JOIN serial ON history.serial = serial.serial
LEFT JOIN employee ON serial.id = employee.serial_id
LEFT JOIN event ON serial.id = event.serial_id
LEFT JOIN location ON location.id = location.serial_id
ORDER BY date, time
正常左连接的结果如下(仅为清楚起见,我不需要此结果集):
查询应基于事件,事件不应为NULL。它应该查看前一行并将其标记为employee(如果不匹配,则为null);它应该查看后一行并将其标记为location(如果不匹配,则为null)。使用上述数据得出的结果示例:
Result should be:
+----------+------------+------------+------------+----------+------------+
| e_serial | date | time | employee | event | location |
+----------+------------+------------+------------+----------+------------+
| 00001235 | 2012-09-25 | 09:01:00 | John Smith | Event 1 | Location 1 |
+----------+------------+------------+------------+----------+------------+
| 00001235 | 2012-09-25 | 09:05:00 | NULL | Event 1 | Location 1 |
+----------+------------+------------+------------+----------+------------+
| 00001235 | 2012-09-25 | 09:10:00 | NULL | Event 1 | NULL |
+----------+------------+------------+------------+----------+------------+
| 00001235 | 2012-09-25 | 09:11:00 | NULL | Event 1 | NULL |
+----------+------------+------------+------------+----------+------------+
| 00001235 | 2012-09-25 | 09:12:00 | NULL | Event 1 | Location 1 |
+----------+------------+------------+------------+----------+------------+
我不确定这在一些子选择集或其他方面是否可行,我认为这远远超过了我使用SQL的能力。目前,我使用应用程序逻辑处理这个问题,但我认为只使用SQL可能会更干净、更快
任何帮助都会很棒
SELECT serial_id AS `serial`,
(SELECT `date` FROM History WHERE serial_id= event2.serial_id ) AS `date`,
(SELECT `time` FROM History WHERE serial_id= event2.serial_id ) AS `time`,
(SELECT `name` FROM event1 WHERE serial_id= event2.serial_id ) AS `event1`,`name` AS event2,
(SELECT `name` FROM event3 WHERE serial_id= event2.serial_id ) AS `event1`
FROM event2
您的历史记录表应该是历史记录(id、序列号、日期、时间)
,必须包含序列号
,而不是序列名
对于您的场景,希望它能正常工作
SELECT serial_id AS `serial`,
(SELECT `date` FROM History WHERE `serial` = (SELECT `serial` FROM `serial` WHERE id = event2.serial_id LIMIT 0,1)) AS `date`,
(SELECT `time` FROM History WHERE `serial`= (SELECT `serial` FROM `serial` WHERE id = event2.serial_id LIMIT 0,1)) AS `time`,
(SELECT `name` FROM event1 WHERE serial_id= event2.serial_id ) AS `event1`,
`name` AS event2,
(SELECT `name` FROM event3 WHERE serial_id= event2.serial_id ) AS `event1`
FROM event2
如果其他人遇到这个问题,请在此处发布解决方案。感谢dianuj为我指引了正确的方向
SELECT
serial.serial as 'e_serial',
@dt:=TIMESTAMP(history.date, history.time) as 'date_time',
history.date,
history.time,
(SELECT
employee.name
FROM
history
LEFT JOIN serial ON history.serial = serial.serial
LEFT JOIN employee ON employee.serial_id = serial.id
WHERE
TIMESTAMP(history.date, history.time) = (
SELECT
max(TIMESTAMP(history.date, history.time))
FROM
history
WHERE TIMESTAMP(history.date, history.time) < @dt
)
) as 'employee',
event.name as 'event',
(SELECT
location.name
FROM
history
LEFT JOIN serial ON history.serial = serial.serial
LEFT JOIN location ON location.serial_id = serial.id
WHERE
TIMESTAMP(history.date, history.time) > @dt
LIMIT 1
) as 'location'
FROM history
LEFT JOIN serial ON history.serial = serial.serial
LEFT JOIN event ON serial.id = event.serial_id
WHERE event.name IS NOT NULL
ORDER BY history.date, history.time
如果您发布每个表的记录而不是连接查询的结果,则会更好:问题是希望它更清楚:)感谢您的回答,不幸的是,无法将serial_id列附加到历史记录表。历史记录中的数据直接来自硬件,硬件提供的所有数据都是序列号。您可以检查第二个查询库,它为我提供了一些帮助,但是您的示例中的event1.serial_id与event2.serial_id不同,因此我无法使用它们加入。我需要的是检查事件2之前和之后的行,并检查匹配项。我想我可能会重写这个问题来澄清,也许它太混乱了。如果你理解上面的mu查询,它只会获取event2表中的
serial\u id
的记录,而不是所有的记录,只获取event2中存在的那些记录,正如你的问题所描述的。希望新问题更有意义
SELECT
serial.serial as 'e_serial',
@dt:=TIMESTAMP(history.date, history.time) as 'date_time',
history.date,
history.time,
(SELECT
employee.name
FROM
history
LEFT JOIN serial ON history.serial = serial.serial
LEFT JOIN employee ON employee.serial_id = serial.id
WHERE
TIMESTAMP(history.date, history.time) = (
SELECT
max(TIMESTAMP(history.date, history.time))
FROM
history
WHERE TIMESTAMP(history.date, history.time) < @dt
)
) as 'employee',
event.name as 'event',
(SELECT
location.name
FROM
history
LEFT JOIN serial ON history.serial = serial.serial
LEFT JOIN location ON location.serial_id = serial.id
WHERE
TIMESTAMP(history.date, history.time) > @dt
LIMIT 1
) as 'location'
FROM history
LEFT JOIN serial ON history.serial = serial.serial
LEFT JOIN event ON serial.id = event.serial_id
WHERE event.name IS NOT NULL
ORDER BY history.date, history.time
+----------+---------------------+------------+----------+------------+---------+------------+
| e_serial | date_time | date | time | employee | event | location |
+----------+---------------------+------------+----------+------------+---------+------------+
| 00001235 | 2012-09-25 09:01:00 | 2012-09-25 | 09:01:00 | John Smith | Event 1 | Location 1 |
| 00001235 | 2012-09-25 09:05:00 | 2012-09-25 | 09:05:00 | NULL | Event 1 | Location 1 |
| 00001235 | 2012-09-25 09:10:00 | 2012-09-25 | 09:10:00 | NULL | Event 1 | NULL |
| 00001235 | 2012-09-25 09:11:00 | 2012-09-25 | 09:11:00 | NULL | Event 1 | NULL |
| 00001235 | 2012-09-25 09:12:00 | 2012-09-25 | 09:12:00 | NULL | Event 1 | Location 1 |
+----------+---------------------+------------+----------+------------+---------+------------+
5 rows in set (0.01 sec)