如何在sql查询中执行此步骤?

时间:2013-05-21 13:46:58

标签: sql oracle oracle11g

我目前正在通过VBA做这个excel,但如果我能在查询中得到一些帮助,那真的会节省很多时间。

这是我正在处理的这份报告需要做的5件事中的一件。

表格
我正在阅读3个不同的表格

TableA   TableB  TableC

tableA

中的字段
OUT_ID

tableB

中的字段
timestamp
event_type
worker
operator_id
new_date

tableC

中的字段
worker

查询

Select
       TableA.OUT_ID,
       TableB.timestamp,
       TableB.new_date,
       TableB.event_type,
       TableC.worker,
       TableB.operator_id

From TableA left outer join
        TableB 
           ON TableA.OUT_ID = TableB.OUT_ID and
                 TableB.event_type in ('WORKER_RET_CMT_CHANCE','RET_CHANCE','WORKER_STATUS_CHANCE') Left OUTER JOIN 
              TableC 
                ON TableB.worker = TableC.worker
 where  TableA.time_stamp > {?PickDate} //parameter in crystal report to pick date
    and TableA.time_stamp < {?RestDate}  //parameter in crystal report to pick date 
   order by TableA.OUT_ID, TableB.timestamp

这是我需要做的事。

Event_type列中RET_CHANCE下一行WORKER_RET_COMMENT_CHANCE,然后检查OUT_ID是否相同,如果相同,则检查TIMESTAMP差异是否小于10秒,如果这一切都是真的,那么将WORKER数字从黄色单元格复制到红色单元格。

请参阅图像打击和附加的excel文件样本。 Download excel file via dropbox

enter image description here

2 个答案:

答案 0 :(得分:1)

这是完整答案,只是尝试澄清任务。它需要一些在注释中不易读的代码。所以(大家)请耐心等待。

以下SELF JOIN是否会创建记录的正确配对

FROM View1 v1
JOIN View1 v2 ON v1.out_id = v2.out_id AND 
                 v1.event_type = 'RET_CHANCE' AND v2.event_type = 'WORKER_RET_COMMENT_CHANCE' AND              
                 ABS(EXTRACT(SECOND FROM v1.timestamp) - EXTRACT(SECOND FROM v2.timestamp)) < 10

答案 1 :(得分:1)

看到您有“下一行”要求,似乎是使用LEAD功能的好时机。

正如文件所述

  

LEAD是一种分析功能。它提供对多行的访问   没有自我加入的同时一张桌子。鉴于一系列   LEAD提供的查询返回的行和游标的位置   访问超出该位置的给定物理偏移量的行

所以为了得到“下一个事件”,“下一个时间戳”和“下一个工作者”我们需要做的事情

LEAD(timestamp) OVER (ORDER BY ???) next_timestamp, 
LEAD(EVENT_TYPE) OVER (ORDER BY ???) next_event,
LEAD(WORKER) OVER (ORDER BY ??) NEXT_WORKER

这里的ORDER BY子句告诉我们“下一行”是什么。 你有

order by TableA.OUT_ID, TableB.timestamp

我们可以做到

... OVER (ORDER BY OUT_ID, timestamp)  

但你也有要求“检查OUT_ID是否相同”。我们可以添加可选的PARTITION BY子句,以确保“下一条记录”用于相同的OUT_ID

... OVER(按时间戳排序按OUT_ID排序)

一旦我们拥有了所有“下一个字段”,我们就可以使用CASE语句来满足剩余的要求

  • 如果Event_type是RET_CHANCE
  • 下一行的事件类型为WORKER_RET_COMMENT_CHANCE
  • 两行的TimeStamps不到10秒
  • 然后使用下一行的工作人员

以下查询是对这些想法的演示。


WITH Data AS (
SELECT 
  OUT_ID,
  timestamp,
  LEAD(timestamp) OVER (PARTITION BY Out_ID ORDER BY TimeStamp) next_timestamp, 
  Event_type,
  LEAD(EVENT_TYPE) OVER (PARTITION BY Out_ID ORDER BY TimeStamp) next_event,
  WORKER,
  LEAD(WORKER) OVER (PARTITION BY Out_ID ORDER BY TimeStamp) NEXT_WORKER
FROM TableB
ORDER BY 
   OUT_ID,
   timestamp
)
SELECT 

  OUT_ID,
  timestamp,
  next_timestamp, 
  Event_type,
  next_event,
  WORKER,
  NEXT_WORKER,
( CAST( next_timestamp AS DATE ) - CAST( timestamp AS DATE ) ) * 86400 DIFF,
  CASE WHEN 
        EVENT_TYPE ='RET_CHANCE'
        AND next_event = 'WORKER_STATUS_CHANCE'
        AND ( CAST( next_timestamp AS DATE ) - CAST( timestamp AS DATE ) ) * 86400  < 10 
       THEN NEXT_WORKER
       ELSE WORKER
   END as CALC_WORKER
FROM 
  data

注意:

  • 您不需要在此使用with子句,但会使CASE语句不可读。
  • 我离开了所有NEXT_ *字段,以便您可以看到查询的工作原理。
  • 使用Jeffrey Kemp的answer计算秒差

DEMO