从MS Access数据库中找出entryTime和exitTime之间的差异

时间:2011-03-03 08:44:36

标签: sql ms-access

我在检索EntryTime和ExitTime之间的区别时遇到了问题。我有一个名为IOData的表,我正在研究IOTime列。 该表的格式为:

HolderName        IODate        IOTime       IOGateName         IOStatus 
Dinesh Kumar    2010/07/09     00:50:05     Basement(I/O)        Entry 
Dinesh Kumar    2010/07/09     00:52:55     Basement(I/O)        Exit 
Dinesh Kumar    2010/07/09     01:00:07     Basement(I/O)        Entry 
Dinesh Kumar    2010/07/09     01:35:42     Basement(I/O)        Exit 
Dinesh Kumar    2010/07/09     01:36:37     Ground Floor(I/O)    Entry 
Dinesh Kumar    2010/07/09     01:37:02     Ground Floor(I/O)    Exit 
Dinesh Kumar    2010/07/09     01:46:04     Ground Floor(I/O)    Entry 
Dinesh Kumar    2010/07/09     01:46:29     Ground Floor(I/O)    Exit 
Dinesh Kumar    2010/07/09     01:47:02     Basement(I/O)        Entry 
Dinesh Kumar    2010/07/09     04:09:11     Basement(I/O)        Exit 
Dinesh Kumar    2010/07/09     04:09:35     Ground Floor(I/O)    Entry 
Dinesh Kumar    2010/07/09     04:11:27     Ground Floor(I/O)    Exit 
Dinesh Kumar    2010/07/09     04:11:54     Basement(I/O)        Entry 
Dinesh Kumar    2010/07/09     05:10:28     Ground Floor(I/O)    Entry 
Dinesh Kumar    2010/07/09     05:18:12     Main Door(I/O)       Exit 
Dinesh Kumar    2010/07/09     17:55:16     Main Door(I/O)       Entry 
Dinesh Kumar    2010/07/09     17:56:10     Ground Floor(I/O)    Entry 

问题是我有一列用于区分时间。我怎样才能克服这个问题。 如果我在两列(进入和退出)中打破IOStatus,那么状态输入可以小于退出或副指令 任何建议将不胜感激 提前致谢

2 个答案:

答案 0 :(得分:1)

我会创建一个视图。

create view suspicious_person_movements as
select IO.holder_name,
cast(IO.io_date || ' ' || IO.io_time as timestamp) as io_timestamp,
-- Concatenate most recent earlier date and time, and cast to timestamp
cast((select max(io_date) 
      from iodata 
      where holder_name = IO.holder_name 
        and io_date <= IO.io_date) 
     || ' ' ||
     (select max(io_time)
      from iodata
      where holder_name = IO.holder_name 
        and io_date <= IO.io_date 
        and io_time < IO.io_time) as timestamp) as previous_timestamp,
-- Subtract the timestamps to get elapsed_time
cast(IO.io_date || ' ' || IO.io_time as timestamp) - 
cast((select max(io_date) 
      from iodata 
      where holder_name = IO.holder_name 
        and io_date <= IO.io_date) || ' ' ||
     (select max(io_time)
      from iodata
      where holder_name = IO.holder_name 
        and io_date <= IO.io_date 
        and io_time < IO.io_time) as timestamp) as elapsed_time,
IO.io_gate_name,
IO.io_status
from iodata IO
order by holder_name, io_date, io_time  -- Better to sort in the client?

然后我可以从suspicious_person_movements中选择所有行。 (轻微编辑以减少水平滚动。)

Dinesh 2010-07-09 00:50:05                                    Basement(I/O)   Entry
Dinesh 2010-07-09 00:52:55   2010-07-09 00:50:05   00:02:50   Basement(I/O)   Exit 
Dinesh 2010-07-09 01:00:07   2010-07-09 00:52:55   00:07:12   Basement(I/O)   Entry
Dinesh 2010-07-09 01:35:42   2010-07-09 01:00:07   00:35:35   Basement(I/O)   Exit 
Dinesh 2010-07-09 01:36:37   2010-07-09 01:35:42   00:00:55   Ground Fl(I/O)  Entry
Dinesh 2010-07-09 01:37:02   2010-07-09 01:36:37   00:00:25   Ground Fl(I/O)  Exit 
Dinesh 2010-07-09 01:46:04   2010-07-09 01:37:02   00:09:02   Ground Fl(I/O)  Entry
Dinesh 2010-07-09 01:46:29   2010-07-09 01:46:04   00:00:25   Ground Fl(I/O)  Exit 
Dinesh 2010-07-09 01:47:02   2010-07-09 01:46:29   00:00:33   Basement(I/O)   Entry
Dinesh 2010-07-09 04:09:11   2010-07-09 01:47:02   02:22:09   Basement(I/O)   Exit 
Dinesh 2010-07-09 04:09:35   2010-07-09 04:09:11   00:00:24   Ground Fl(I/O)  Entry
Dinesh 2010-07-09 04:11:27   2010-07-09 04:09:35   00:01:52   Ground Fl(I/O)  Exit 
Dinesh 2010-07-09 04:11:54   2010-07-09 04:11:27   00:00:27   Basement(I/O)   Entry
Dinesh 2010-07-09 05:10:28   2010-07-09 04:11:54   00:58:34   Ground Fl(I/O)  Entry
Dinesh 2010-07-09 05:18:12   2010-07-09 05:10:28   00:07:44   Main Door(I/O)  Exit 
Dinesh 2010-07-09 17:55:16   2010-07-09 05:18:12   12:37:04   Main Door(I/O)  Entry
Dinesh 2010-07-09 17:56:10   2010-07-09 17:55:16   00:00:54   Ground Fl(I/O)  Entry

我以最明显的方式实现了视图。您需要持有者姓名,日期和时间的索引。通过将表连接到自身而不是使用这些标量子查询,可以获得更好的性能。无论哪种方式,大型数据集的性能可能都不是很好。 (但您通常可以限制持有人姓名和日期范围,这将有所帮助。)


对于Access,您将使用更像这样的查询,我从SQL视图中复制。

SELECT IO.holder_name
     , [io_date] & " " & [io_time] AS io_timestamp
     , (select max(io_date) 
        from iodata 
        where holder_name = IO.holder_name 
          and io_date <= IO.io_date) 
          & " " & 
       (select max(io_time)
        from iodata
        where holder_name = IO.holder_name 
          and io_date <= IO.io_date 
          and io_time < IO.io_time) AS previous_timestamp
     , DateDiff("n",[previous_timestamp],[io_timestamp]) AS elapsed_minutes
     , IO.io_gate_name
     , IO.io_status
FROM iodata AS IO
ORDER BY IO.holder_name, IO.io_date, IO.io_time;

我采取了一些捷径,因为我在工作。我以“00:00:00”格式显示经过的分钟而不是经过的时间。我忽略第一行的空时间戳。

答案 1 :(得分:1)

如果可能的话(我意识到这可能为时已晚),我建议您重新设计您的架构。以下似乎更有意义:

HolderName      IOGateName        EnterDT              ExitDT 
Dinesh Kumar    Basement(I/O)     2010/07/09 00:50:05  2010/07/09 00:52:55
Dinesh Kumar    Basement(I/O)     2010/07/09 01:00:07  2010/07/09 01:35:42
Dinesh Kumar    Ground Floor(I/O) 2010/07/09 01:36:37  2010/07/09 01:37:02

请注意,虽然它看起来可能看起来像数据较少,但实际上并没有丢失任何信息...只是规范化您的结构。

在数据输入方面需要一些小心。例如,除了INSERT之外,您还需要执行UPDATE。如果可能的话,您可能需要处理嵌套位置(例如,实验室内的洁净室,洁净室的入口/出口将介于实验室本身的进入和退出事件之间)。

所有这些事情仍然可以通过这种设计来处理,报告将大大简化并提高效率。

回答关于在某个地点花费的时间的原始问题现在很简单。