【问题标题】:how to perform this step in sql query?如何在sql查询中执行这一步?
【发布时间】:2013-05-21 13:46:58
【问题描述】:

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

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

表格
我正在阅读 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 秒,如果所有这些都是真的,则复制@ 987654333@从黄色单元格到红色单元格的数字。

请参阅图片和附加的 excel 文件以获取示例。 Download excel file via dropbox

【问题讨论】:

  • 我会将它用于赏金或 Paypal 租用,但我需要的不仅仅是 1 个步骤。如果有人有兴趣,请通过电子邮件与我联系
  • 你最好正式定义这些记录的顺序,因为没有它“下一行”是没有意义的。
  • @DavidAldridge 很少WORKER_ERT_COMMENT_CHANCE 将在第一行,RET_CHANCE 将在下一行,如果这种情况比我需要执行相同的步骤。回到你的问题,它是由@订购987654336@, TableA.timestamp
  • 这不足以定义为什么 RET_CHANCE 是“之前” WORKER_RET_COMMENT_CHANCE。
  • 您是说根据您在查询中指定的ORDER BY 子句,“下一行”的意思不是下一行吗?或者我们可以只看timestamp 为特定的out_id 排序的下一行吗?

标签: sql oracle oracle11g


【解决方案1】:

不是完整的答案,只是试图澄清任务。它需要一些在 cmets 中不太可读的代码。所以(大家)请多多包涵。

以下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

【讨论】:

  • 谢谢,我从来没有使用过视图,但只看它在我看来的状态。
  • 我刚刚将您的结果数据集命名为 View1,因此我不必将您的整个查询包含在我的答案中。
  • ABS(EXTRACT(SECOND FROM v1.timestamp) - EXTRACT(SECOND FROM v2.timestamp)) 不正确。这减去了时间戳的第二部分。
  • 我猜Ask Tom的解决方案没有替代品:asktom.oracle.com/pls/asktom/…
【解决方案2】:

看到您有“下一行”要求,似乎是使用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 的 answer 计算秒差

DEMO

【讨论】:

  • 在 Oracle 中,DATE 类型字段的减法会在 内产生结果。您的逻辑不会丢失时间组件吗?
  • @PM77-1 我想证据就在布丁里。它不在SQLFiddle 中,请参阅 Diff 列。当我尝试使用您的Extract method it didn't work 时。另请注意,asktom 文章使用日期数据类型
  • 我不确定你的意思。我已经更新了我的答案以包含解决方案的描述。有什么特别的地方我没有解释清楚吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-21
  • 1970-01-01
  • 2020-02-21
  • 2021-07-04
相关资源
最近更新 更多