2

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

这是我正在编写的这份报告需要做的 5 件事中的 1 件。


我正在从 3 个不同的表中读取

TableA   TableB  TableC

表 A中的字段

OUT_ID

表 B中的字段

timestamp
event_type
worker
operator_id
new_date

表 C中的字段

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有,则检查是否相同,如果相同,则检查差异是否小于 10 秒,如果所有这些都是正确的,则从黄色单元格到红色单元格的复制数。WORKER_RET_COMMENT_CHANCEOUT_IDTIMESTAMPWORKER

请参阅图像打击和附加的 excel 文件以获取示例。 通过 Dropbox 下载 excel 文件

在此处输入图像描述

4

2 回答 2

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 (PARTITION BY OUT_ID ORDER BY timestamp)

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

  • 如果 Event_type 是 RET_CHANCE
  • 并且下一行的事件类型是 WORKER_RET_COMMENT_CHANCE
  • 并且两行的时间戳小于 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 的答案计算秒差

演示

于 2013-05-21T17:57:51.973 回答
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
于 2013-05-21T16:28:36.780 回答