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. SELECTlog_tsの順序で行を作成し、行番号を各行に関連付けます。
  2. SELF JOINfirstTable.rownum = secondTable.rownum -1の#1の結果。ワークテーブルの各行には、現在のレコードと次のレコードが含まれます。
  3. WHEREコスト値が異なり、の2番目のセットのタプルに関心があるように句を適用します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

これは、セットベースのロジック(sql)ではなく、手続き型ロジック(コード)に非常に適しています。そのため、可能であれば、データセットを並べ替えてループできるコードで実行することをお勧めします。

コードがオプションでない場合は、カーソルとループを使用してストアドプロシージャで同じことを行うことができます。

于 2012-09-19T04:09:18.587 に答える
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
     )

DISTINCTテーブルに(PO、log_Ts)の一意のインデックスがある場合は、を削除できます。

于 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 に答える