1

有一个记录集,我希望根据 PO 获取最短日期的记录,直到成本发生变化。任何帮助,将不胜感激。大约有 700 万条记录,而当前光标并没有切断它。

样本:

PO       log_Ts                         cost
123      2012-06-26-10.37.44.035385     2.5896
123      2012-06-27-02.16.14.706817     2.5896
123      2012-06-26-10.28.57.540731     2.591
123      2012-06-26-10.37.43.948940     2.5896
123      2012-06-26-10.37.43.421713     2.5896
123      2012-06-26-18.34.37.191917     2.5896
123      2012-06-27-02.16.14.705622     2.5896
123      2012-06-27-04.33.18.264742     2.5896
123      2012-06-26-10.37.44.007667     2.5896
123      2012-06-26-10.37.43.706207     2.5896
123      2012-06-26-10.26.56.767121     2.5896
123      2012-06-26-10.37.43.919248     2.5896

Looking to grab:
PO       log_Ts                         cost
123      2012-06-26-10.26.56.767121     2.5896
123      2012-06-26-10.28.57.540731     2.591
123      2012-06-26-10.37.43.421713     2.5896
4

4 回答 4

1

您可以尝试以下方法:

  1. SELECT按 log_ts 顺序排列的行,并将行号与每一行相关联。
  2. SELF JOIN#1 中 firstTable.rownum = secondTable.rownum -1 的结果。工作表中的每一行都将包含当前记录和下一条记录。
  3. 应用该WHERE子句,使成本值不同,并且您对SELF JOIN.

例如

RowNum  PO       log_Ts                         cost    RowNum  PO       log_Ts                         cost
1       123      2012-06-26-10.37.44.035385     2.5896  2       123      2012-06-27-02.16.14.706817     2.5896
2       123      2012-06-27-02.16.14.706817     2.5896  3       123      2012-06-26 10.28.57.540731     2.591
3       123      2012-06-26-10.28.57.540731     2.591   4       123      2012-06-26-10.37.43.948940     2.5896

询问:

WITH T (PO, Log_Ts, Cost, RowNum) 
AS 
(
SELECT PO, Log_Ts, Cost, Row_Number() OVER(ORDER BY Log_Ts) FROM PO_INFO
) 

SELECT T2.* 
FROM 
    T t1
    JOIN T t2
    ON t1.rownum = t2.rownum - 1 AND t1.cost != t2.cost

结果:

123      2012-06-26 10.28.57.540731     2.591    2
123      2012-06-26-10.37.43.948940     2.5896   3

HTH。

于 2012-09-19T04:10:18.403 回答
0

如果您的 DBMS 支持 LAG() 函数,则可以在 t-clausen.dk 和 Vikdor 的答案中使用 CTE 方法,但不需要自连接。

WITH t 
AS 
(
    SELECT PO, log_Ts, Cost, 
    LAG( Cost ) OVER( PARTITION BY PO ORDER BY log_Ts) AS prevcost
    FROM po_log_events
) 
SELECT PO, log_Ts, Cost
FROM t
WHERE prevcost IS NULL 
OR prevcost <> cost       
ORDER BY PO, log_Ts

如果 ROW_NUMBER() 和公用表表达式不适用于您的数据库(即您的数据库是 MySQL),则可以通过相关子查询实现相同的结果:

SELECT DISTINCT p.PO, p.log_Ts, p.Cost
FROM po_log_events p
WHERE NOT EXISTS 
    ( SELECT 1 FROM po_log_events p2 
      WHERE p2.PO = p.PO AND p2.log_Ts < p.log_Ts )
OR NOT EXISTS 
    ( SELECT 1 FROM po_log_events p3 
      WHERE p3.PO = p.PO 
      AND p3.log_Ts = 
          (SELECT MAX(p4.log_ts) 
           FROM po_log_events p4
           WHERE p4.PO = p.PO
           AND p4.log_Ts < p.log_Ts
           )
      AND p3.Cost = p.Cost
     )

如果表在 (PO, log_Ts) 上有唯一索引,DISTINCT则可以删除

于 2012-09-19T05:20:21.910 回答
0
;with a as
(
  select po, log_ts, cost, row_number() over (partition by po order by log_ts) rn
  from <table>
), b as
(
  select po, log_ts, cost, 1 grp, rn from a where rn = 1
  union all
  select a.po, a.log_ts, a.cost, case when a.cost = b.cost then b.grp else b.grp+1 end, a.rn
  from a
  join b on a.rn = b.rn+1 and a.po = b.po
)
select po, min(log_ts) log_ts, cost 
from b
group by po, cost, grp
于 2012-09-19T05:35:42.573 回答
0

这是真正适用于过程逻辑(代码)而不是基于集合的逻辑(sql)的东西。因此,如果可能的话,我建议在代码中执行此操作,您可以简单地对数据集进行排序并循环遍历它。

如果代码不是一个选项,您可以使用游标和循环在存储过程中执行相同的操作。

于 2012-09-19T04:09:18.587 回答