2012-09-25 80 views
1

我在MySQL中有五个表,我正在生成一些报告。为了显示目的,我会略微提取表名。假设我一起工作的表是如下所述:MySQL在查询中获取当前行之前和之后的行

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) 

编辑:重写了,希望整个问题,它更清晰,更容易理解......

我需要查询事件,如果直接在历史中发现员工序列PRIOR到一个串行匹配事件的行,该员工将与该事件相关联,同样,如果直接在历史记录中找到位置AFTER行与序列匹配一个事件,该位置将与该关联t事件。

的样本数据:

History: 
+------+------------+------------+----------+ 
| id | serial  | date  | time  | 
+------+------------+------------+----------+ 
| 1 | 000| 2012-09-25 | 09:00:00 | 
+------+------------+------------+----------+ 
| 2 | 000| 2012-09-25 | 09:01:00 | 
+------+------------+------------+----------+ 
| 3 | 000| 2012-09-25 | 09:02:00 | 
+------+------------+------------+----------+ 
| 4 | 000| 2012-09-25 | 09:05:00 | 
+------+------------+------------+----------+ 
| 5 | 000| 2012-09-25 | 09:07:00 | 
+------+------------+------------+----------+ 
| 6 | 000| 2012-09-25 | 09:10:00 | 
+------+------------+------------+----------+ 
| 7 | 000| 2012-09-25 | 09:11:00 | 
+------+------------+------------+----------+ 
| 8 | 000| 2012-09-25 | 09:12:00 | 
+------+------------+------------+----------+ 
| 9 | 000| 2012-09-25 | 09:15:00 | 
+------+------------+------------+----------+ 
| 10 | 000| 2012-09-25 | 09:20:00 | 
+------+------------+------------+----------+ 
| 11 | 000| 2012-09-25 | 09:25:00 | 
+------+------------+------------+----------+ 

Serial: 
+----------+------------+ 
| id  | serial  | 
+----------+------------+ 
| 1  | 000| 
+----------+------------+ 
| 2  | 000| 
+----------+------------+ 
| 3  | 000| 
+----------+------------+ 

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 | 
+----------+------------+-------------+ 

如果我做一个正常的LEFT JOIN查询(只是为了清楚起见,在结果的差异),用下面的查询,结果将是:

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 
正常LEFT

JOIN的结果是(为清楚起见而已,我不需要这个结果集):

+----+----------+------------+----------+------------+----------+------------+ 
| id | serial | date  | time  | employee | event | location | 
+----+----------+------------+----------+------------+----------+------------+ 
| 1 | 000| 2012-09-25 | 09:00:00 | John Smith | NULL  | NULL  | 
+----+----------+------------+----------+------------+----------+------------+ 
| 2 | 000| 2012-09-25 | 09:01:00 | NULL  | Event 1 | NULL  | 
+----+----------+------------+----------+------------+----------+------------+ 
| 3 | 000| 2012-09-25 | 09:02:00 | NULL  | NULL  | Location 1 | 
+----+----------+------------+----------+------------+----------+------------+ 
| 4 | 000| 2012-09-25 | 09:05:00 | NULL  | Event 1 | NULL  | 
+----+----------+------------+----------+------------+----------+------------+ 
| 5 | 000| 2012-09-25 | 09:07:00 | NULL  | NULL  | Location 1 | 
+----+----------+------------+----------+------------+----------+------------+ 
| 6 | 000| 2012-09-25 | 09:10:00 | NULL  | Event 1 | NULL  | 
+----+----------+------------+----------+------------+----------+------------+ 
| 7 | 000| 2012-09-25 | 09:11:00 | NULL  | Event 1 | NULL  | 
+----+----------+------------+----------+------------+----------+------------+ 
| 8 | 000| 2012-09-25 | 09:12:00 | NULL  | Event 1 | NULL  | 
+----+----------+------------+----------+------------+----------+------------+ 
| 9 | 000| 2012-09-25 | 09:15:00 | NULL  | NULL  | Location 1 | 
+-----+---------+------------+----------+------------+----------+------------+ 
| 10 | 000| 2012-09-25 | 09:20:00 | John Smith | NULL  | NULL  | 
+----+----------+------------+----------+------------+----------+------------+ 
| 11 | 000| 2012-09-25 | 09:25:00 | NULL  | NULL  | Location 1 | 
+----+----------+------------+----------+------------+----------+------------+ 

查询S应该基于事件,事件不应该是NULL。它应该查看行PRIOR并将其标记为员工(如果不匹配则为空),则应查看之后的行并将其标记为位置(如果不匹配,则为null)。结果应该是什么,使用上述数据举例:

Result should be: 
+----------+------------+------------+------------+----------+------------+ 
| e_serial | date  | time  | employee | event | location | 
+----------+------------+------------+------------+----------+------------+ 
| 000| 2012-09-25 | 09:01:00 | John Smith | Event 1 | Location 1 | 
+----------+------------+------------+------------+----------+------------+ 
| 000| 2012-09-25 | 09:05:00 | NULL  | Event 1 | Location 1 | 
+----------+------------+------------+------------+----------+------------+ 
| 000| 2012-09-25 | 09:10:00 | NULL  | Event 1 | NULL  | 
+----------+------------+------------+------------+----------+------------+ 
| 000| 2012-09-25 | 09:11:00 | NULL  | Event 1 | NULL  | 
+----------+------------+------------+------------+----------+------------+ 
| 000| 2012-09-25 | 09:12:00 | NULL  | Event 1 | Location 1 | 
+----------+------------+------------+------------+----------+------------+ 

我不知道这是可能的一些子集选择什么的,我觉得这是在我的联赛SQL的方式。目前,我已经与应用程序逻辑一起工作,但认为只用SQL来处理它可能更干净更快。

任何帮助将是太棒了。

+1

好得多,如果您发布的每个表的记录中加入了查询没有结果:d –

+0

改写的问题是希望它应该是更清楚:) –

回答

1

万一别人永远运行到这个问题,发帖这里的解决方案。感谢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 

而且结果

+----------+---------------------+------------+----------+------------+---------+------------+ 
| e_serial | date_time   | date  | time  | employee | event | location | 
+----------+---------------------+------------+----------+------------+---------+------------+ 
| 000| 2012-09-25 09:01:00 | 2012-09-25 | 09:01:00 | John Smith | Event 1 | Location 1 | 
| 000| 2012-09-25 09:05:00 | 2012-09-25 | 09:05:00 | NULL  | Event 1 | Location 1 | 
| 000| 2012-09-25 09:10:00 | 2012-09-25 | 09:10:00 | NULL  | Event 1 | NULL  | 
| 000| 2012-09-25 09:11:00 | 2012-09-25 | 09:11:00 | NULL  | Event 1 | NULL  | 
| 000| 2012-09-25 09:12:00 | 2012-09-25 | 09:12:00 | NULL  | Event 1 | Location 1 | 
+----------+---------------------+------------+----------+------------+---------+------------+ 
5 rows in set (0.01 sec) 
1
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 

您histroy表应该是History (id, serial_id, date, time),必须包含serial_id代替serial name

您的方案,希望这样能正常工作

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 
+0

感谢您的答案,不幸的是,无法将serial_id列附加到历史记录表。历史数据直接来自硬件,所有硬件提供的都是序列号。 –

+0

好的我将编辑我的答案为上述情况 –

+0

您可以检查第二个查询 –

相关问题