【问题标题】:SQL to improve performance提高性能的 SQL
【发布时间】:2014-01-04 20:08:47
【问题描述】:

这是我的问题,我有一个表格(在 Excel 表中,并使用 Microsoft.ACE.OLEDB.12.0 连接它),其中包含以下列格式跟踪来自 RF 读卡器的输入/输出卡刷卡的各种列。 ..

Date, Time Occurred, Employee Number, Employee Name, Location
2013-12-20, 11:10:23 AM, 123456, Tester, Door001 IN
2013-12-20, 11:21:44 AM, 123456, Tester, Door002 OUT
2013-12-20, 12:00:12 AM, 123456, Tester, Door001 IN
2013-12-20, 01:00:23 PM, 123456, Tester, Door002 IN
2013-12-20, 03:40:43 PM, 123456, Tester, Door001 OUT
2013-12-20, 05:00:58 PM, 123456, Tester, Door004 IN
2013-12-20, 05:50:02 PM, 123456, Tester, Door001 OUT
2013-12-20, 05:10:00 PM, 123456, Tester, Door002 OUT
2013-12-20, 11:00:01 PM, 123456, Tester, Door001 IN
2013-12-20, 09:10:23 AM, 789012, Developer, Door001 IN
2013-12-20, 10:00:44 AM, 789012, Developer, Door002 OUT
2013-12-20, 10:01:12 AM, 789012, Developer, Door003 IN
2013-12-20, 11:00:23 AM, 789012, Developer, Door004 OUT
2013-12-20, 02:40:43 PM, 789012, Developer, Door005 IN
2013-12-20, 01:00:58 PM, 789012, Developer, Door006 OUT
2013-12-20, 06:50:02 PM, 789012, Developer, Door007 IN
2013-12-20, 08:00:00 PM, 789012, Developer, Door008 IN
2013-12-20, 09:00:01 PM, 789012, Developer, Door009 OUT

我想要以下格式的输出:

Date,Employee Id, Employee Name, First In Time, First In Door Name, Last out time, Last Out Door Name
2013-12-20, 123456, Tester, 12:00:12 AM, Door001 IN, 11:00:01 PM, Door001 OUT
2013-12-20, 789012, Developer, 9:10:23 AM, Door001 IN, 9:00:01 PM, Door009 OUT

请注意,First In Time 和 Last Out 时间来自原始数据中的同一列,First In Door Name 和 Last Out Door Name 类似

我有这个工作,但我认为没有性能...... 目前,我正在编写一个从源表中获取不同员工 ID 的 SQL。

SELECT DISTINCT [Employee Number] 
FROM [Sheet1$]

然后我启动两个单独的查询以获取 Excel 中的第一个时间和第一个门名称存储,并启动另一个查询最后一个和最后一个门。

SELECT * 
FROM   [sheet1$] 
WHERE  ( [employee number] = '" & Trim(rst.Fields(0).Value) & "' ) 
       AND ( location LIKE '% IN%' ) 
       AND ( 
[sheet1$].[time occurred] >= '" & Format(startTime, "hh:mm:ss") & "' 
AND [sheet1$].[time occurred] <= '" & Format(endTime, "hh:mm:ss") & "' ) 
ORDER  BY [time occurred] ASC 


SELECT * 
FROM   [sheet1$] 
WHERE  ( [employee number] = '" & Trim(rst.Fields(0).Value) & "' ) 
       AND ( location LIKE '% OUT%' ) 
       AND ( 
[sheet1$].[time occurred] >= '" & Format(startTime, "hh:mm:ss") & "' 
AND [sheet1$].[time occurred] <= '" & Format(endTime, "hh:mm:ss") & "' ) 
ORDER  BY [time occurred] DESC 

对于给定的时间过滤器,为了获得“时间第一/门”,我使用 ASC 排序,对于“最后出/门”,我使用 ASC/DESC 排序并从结果中提取第一行。问题是在典型的一天,我可以在大楼里看到大约 10000 名唯一员工,因此为每个员工编号触发两个查询(因此 20000 个查询)需要很长时间。更糟糕的是,我正在编写这是一个 VB 宏,因此添加循环、if 块条件等以进行处理,这使得获取数据的速度有点慢。

只是想如果我可以避免这 20000 个查询并且以某种方式对所有这些提取只有一个查询,我认为它必须更快。有什么想法可以通过在一个 SQL 中作为输出而不是 20000 个查询来减少逻辑吗? 仅供参考,我尝试使用 JOIN,但不知何故我没有得到它:(

【问题讨论】:

  • 使用哪个数据库引擎来处理查询?

标签: sql performance date time oledb


【解决方案1】:

使用动态列查询:

SELECT E.EMP_ID, 
(SELECT MIN(SWIPE_TIME) FROM SWIPES WHERE EMP_ID = E.EMP_ID AND DOOR_NAME LIKE '%IN%') AS TIME_IN, 
(SELECT DOOR_NAME FROM SWIPES WHERE EMP_ID = E.EMP_ID AND SWIPE_TIME = TIME_IN) AS DOOR_IN,
(SELECT MAX(SWIPE_TIME) FROM SWIPES WHERE EMP_ID = E.EMP_ID AND DOOR_NAME LIKE '%OUT%') AS TIME_OUT, 
(SELECT DOOR_NAME FROM SWIPES WHERE EMP_ID = E.EMP_ID AND SWIPE_TIME = TIME_OUT) AS DOOR_IN,
FROM SWIPES E
GROUP BY E.EMP_ID;

没有动态列的查询:

SELECT E.EMP_ID, 
(SELECT MIN(SWIPE_TIME) FROM SWIPES WHERE EMP_ID = E.EMP_ID AND DOOR_NAME LIKE '%IN%') AS TIME_IN, 
(SELECT DOOR_NAME FROM SWIPES WHERE EMP_ID = E.EMP_ID AND SWIPE_TIME = 
    (SELECT MIN(SWIPE_TIME) FROM SWIPES WHERE EMP_ID = E.EMP_ID AND DOOR_NAME LIKE '%IN%')
) AS DOOR_IN,
(SELECT MAX(SWIPE_TIME) FROM SWIPES WHERE EMP_ID = E.EMP_ID AND DOOR_NAME LIKE '%OUT%') AS TIME_OUT, 

(SELECT DOOR_NAME FROM SWIPES WHERE EMP_ID = E.EMP_ID AND SWIPE_TIME = 
    (SELECT MAX(SWIPE_TIME) FROM SWIPES WHERE EMP_ID = E.EMP_ID AND DOOR_NAME LIKE '%OUT%')

) AS DOOR_OUT
FROM SWIPES E
GROUP BY E.EMP_ID;

我已根据我们的讨论更新了查询。

【讨论】:

  • 好的,这里我有两个逻辑数据要选择 - 1)第一个时间对应于 '% IN' 的位置 2)最后一个时间对应于 '% OUT' 的位置 .... 怎么做我通过您的查询来实现这一点?
  • 一个问题:员工有没有可能有时间少于时间?
  • 是的,想象一下管理员想要过滤特定时间段的记录的情况,比如下午 1 点到 2 点,在这种情况下,您可能会看到 OUT 比 IN 更早滑动(比如说他出去了烟雾 ;) )
  • 我已经修改了查询。请检查是否有效。不过需要更改列名和表名。
  • 谢谢Darshan,它至少给了我一些思考的线索。但是...我尝试使用您的查询,它抱怨“参数太少”...我怀疑这是由于我们动态创建的 [TIME_IN] 和 [TIME_OUT] 列。如果在过滤位置时将 [TIME_IN] 和 [TIME_OUT] 替换为一个值,它会触发查询,但是当我使用 [TIME_IN] 和 [TIME_OUT] 时会抱怨.....有什么建议吗?
猜你喜欢
  • 2010-10-09
  • 2017-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-12
相关资源
最近更新 更多