制作太多的表副本

时间:2011-06-23 19:08:50

标签: sql

我正在将一个查询写入一个跟踪销售员状态的表格,并跟踪他们的旅行时间。作为参考,以下是对此问题很重要的状态:

0:初始值,正在运行

600:旅行休息

601:休息时间

603:去吃午餐

604:午餐时

我正在计算员工花在旅行上的总时间。我可以使用

返回旅行时间和午餐时间
SELECT (cast(c1.status_change_dt as date) - cast(c2.status_change_dt as date)) as LunchTravel, C1.CREW_ID
FROM CREW_STATUS c1, CREW_STATUS c2
WHERE c1.status_id = '603' and c2.status_id = '602'
and c1.mobile_token = c2.mobile_token

与休息一样。 Mobile_token是为了确保它在同一天被返回(每个员工每天都获得一个唯一的令牌)。

Status_change_dt是时间戳

我做同样的事情,但另一个status_id是为了获得BreakTravel时间。

所以我最终得到了LunchTravel和BreakTravel,但我觉得创建4个Crew_Status效率很低,实际上运行速度很慢。

有更好的方法吗?

3 个答案:

答案 0 :(得分:1)

如果我理解你的问题,我认为你可以使用UNION ALL或CASE声明。

SELECT (cast(c1.status_change_dt as date) - cast(c2.status_change_dt as date))
, CASE WHEN c1.status_id = '603' and c2.status_id = '602' THEN 'Lunch Travel'
,      WHEN c1.status_id = '604' and c2.status_id = '605' THEN 'Break Travel'
END AS travel_type
FROM CREW_STATUS c1, CREW_STATUS c2
WHERE c1.mobile_token = c2.mobile_token

OR

SELECT (cast(c1.status_change_dt as date) - cast(c2.status_change_dt as date)) as Travel, 'Lunch Travel' AS travel_type, C1.CREW_ID
FROM CREW_STATUS c1, CREW_STATUS c2
WHERE c1.status_id = '603' and c2.status_id = '602'
and c1.mobile_token = c2.mobile_token

UNION ALL

SELECT (cast(c1.status_change_dt as date) - cast(c2.status_change_dt as date)) as Travel, 'Break Travel' AS travel_type, C1.CREW_ID
FROM CREW_STATUS c1, CREW_STATUS c2
WHERE c1.status_id = '605' and c2.status_id = '606'
and c1.mobile_token = c2.mobile_token

答案 1 :(得分:0)

而不是尝试加入状态(如何确保602之后的行是603?)我会按日期加入以获得一个结果集,该结果集可以为您提供状态之间的时间:

SELECT
    CS1.status_id,
    CS2.status_change_dt - CS1.status_change_dt  -- Use date function here
FROM
    Crew_Status CS1
INNER JOIN Crew_Status CS2 ON
    CS2.mobile_token = CS1.mobile_token AND
    CS2.status_change_dt > CS1.status_change_dt
LEFT OUTER JOIN Crew_Status CS3 ON
    CS3.mobile_token = CS1.mobile_token AND
    CS3.status_change_dt > CS1.status_change_dt AND
    CS3.status_change_dt < CS2.status_change_dt
WHERE
    CS3.status_change_dt IS NULL

然后,您可以按status_idSUM分组日期差异以获得总数。

您可能需要添加一些不同的检查 - 确保CS1.status_id和CS2.status_id有意义(例如602和603)并占用过长的时间(如果员工继续,会发生什么情况)休息,但是没有进一步的状态记录?看起来好像他们休息了3天。

最后,停止尝试监控销售人员的每一天,让他们完成工作;)

答案 2 :(得分:0)

如果您的数据库支持它们,您可能只需使用分析查询来获取指示休息开始的每个状态的下一个状态:

select mobile_token, end_dt - start_dt
from (select status_id, 
             mobile_token,
             status_change_dt as start_dt, 
             lead(status_change_dt) over (partition by mobile_token
                                          order by status_change_dt) as end_dt
      from Crew_Status)
where status_id in (600, 603)

显然,如果你可以拥有600而没有601(例如),这将不会特别好(对于接下来发生的任何事情,返回的时间段将是600)。

顺便说一句,指定您正在使用的数据库总是一个好主意,因为它们之间的功能可能会有很大差异。