2011-10-28 3 views
4

私はSELECT * FROM table ORDER BY tick,refidから、次の(簡体字)の結果があります。以前の値から欠落した行を `選択 'して製造する方法は?

tick refid value 
---------------- 
1 1  11 
1 2  22 
1 3  33 
2 1  1111 
2 3  3333 
3 3  333333 

注REFID 1(3ティック)のための "行方不明" の行をして、どのように(2ティック及び3)

可能な場合は2をREFIDこれらの欠落している行を追加するクエリを作成するには、その前にvalueという最新のものを使用してください。refid? 「最新のもの」とは、欠けている行と同じrefidを持つ行の値と、その行のtickが欠落している行のtickよりも小さいような最大のtickを意味します。例えば

tick refid value 
---------------- 
1 1  11 
1 2  22 
1 3  33 
2 1  1111 
2 2  22 
2 3  3333 
3 1  1111 
3 2  22 
3 3  333333 

追加条件:

  • すべてrefidsティック= 1での値を持つことになります。
  • refidには、(refid 2の場合と同様に)多くの 'missing'ダニがある場合があります。
  • 多くのrefidsがあり、どこにスパースデータがあるかはわかりません。
  • 3を超える多くのダニがありますが、すべて連続します。正しい結果では、それぞれのヒダリの結果がそれぞれのヒントになります。
  • 不足している行は事前に分かっていません。これは、すべてが同じ構造で、複数のデータベースで実行され、異なる「行がありません」行です。

私はMySQLを使用しており、今すぐdbを変更することはできません。議論を助けるために別の方言で回答を投稿しても構いませんが、私は他の人よりもMySQL方言で答えを選択します。

はい、これは私が実装したコードで行うことができます。私はそれがSQLで行うことができるのか不思議です。

+1

"最近の"とは、欠けている行と同じrefidを持つ行の 'value'と' tick 'が欠落している行の 'tick'となるような最大の' tick'を意味しますか? ?完全に欠けている(すなわち、テーブルに全く現れない)「ティック」はありますか?追加する必要がありますか? – outis

+0

@outは「最新の」「値」の定義上正しい。 (私は野生でそれを見たことはないが)正確に欠けている可能性があると信じています。 – Chadwick

答えて

3

指定されたtick-refidの組み合わせが存在しない場合は、valueは返されますか?この解決法では、与えられたrefidの最低値を返すだけでした。私がnullの場合に使用するためにどのような値を決定するためのロジックを更新しました

リビジョン

。私はtick + refidがテーブル内で一意であると仮定していることに注意してください。

 SELECT a.tick, b.refid 
     FROM (SELECT DISTINCT tick FROM t) a 
CROSS JOIN (SELECT DISTINCT refid FROM t) b 

そのクエリから今substract既存のもの:

 SELECT a.tick tick, b.refid refid 
     FROM (SELECT DISTINCT tick FROM t) a 
CROSS JOIN (SELECT DISTINCT refid FROM t) b 
MINUS 
    SELECT DISTINCT tick, refid FROM t 

全体のリストを取得挿入するペア(REFID、ダニ)のリストを持っているために、

Select Ticks.tick 
    , Refs.refid 
    , Case 
     When Table.value Is Null 
      Then (
        Select T2.value 
        From Table As T2 
        Where T2.refid = Refs.refId 
         And T2.tick = (
             Select Max(T1.tick) 
             From Table As T1 
             Where T1.tick < Ticks.tick 
              And T1.refid = T2.refid 
             ) 
        ) 
     Else Table.value 
     End As value 
From (
     Select Distinct refid 
     From Table 
     ) As Refs 
    Cross Join (
       Select Distinct tick 
       From Table 
       ) As Ticks 
    Left Join Table 
     On Table.tick = Ticks.tick 
      And Table.refid = Refs.refid 
+0

欠落した行に挿入される値は、そのrefidに見られる最新のもの(順序付けられたティックに基づく)でなければなりません。 refid = 1の例を参照してください。 – Chadwick

+0

@Chadwick - ティック743で作業していて、refid32がないとします。今度は、ティック740にrefid32の値があり、ティック744にrefid32の値があるとします。 – Thomas

+0

@Chadwick - また、このテーブルには1つの整数の主キーがありますか? – Thomas

0

あなたは「ダニ」と「REFID」の値が何であるかを事前に知っていれば、

  1. は、すべての可能なダニやREFID値が含まれているヘルパー表を作成します。
  2. その後、チックのヘルパーテーブルから結合し、データテーブルにrefidを残します。

「tick」と「refid」の値が正確にわからない場合は、このメソッドを使用できますが、静的ヘルパー・テーブルの代わりに動的に生成する必要があります。

+0

どの行が欠落しているかは分かりません。これを含めるように質問を編集しました。 – Chadwick

0

今度は、tと結合して最終クエリを得ることができます(前の結果を得るために内部結合+左結合を使用しますが、適応することができます)。

INSERT INTO t(tick, refid, value) 
SELECT c.tick, c.refid, t1.value 
    FROM (  SELECT a.tick tick, b.refid refid 
        FROM (SELECT DISTINCT tick FROM t) a 
      CROSS JOIN (SELECT DISTINCT refid FROM t) b 
      MINUS 
       SELECT DISTINCT tick, refid FROM t 
     ) c 
INNER JOIN t t1 ON t1.refid = c.refid and t1.tick < c.tick 
    LEFT JOIN t t2 ON t2.refid = c.refid AND t1.tick < t2.tick AND t2.tick < c.tick 
WHERE t2.tick IS NULL 
+0

このアプローチは他のRDBMSでも動作するかもしれませんが、MySQLはMINUSをサポートしていません。派生テーブル 'c'には' value'カラムはありません。 't1.value'を意味しましたか?また、t1とt2に対してjoin句で 'tick 'と' refid'を入れ替えたようです。 – outis

0

以下は私の好みのサブ選択肢が多すぎますが、すべてのティックとすべてのrefidがテーブル内で少なくとも1回は別々に発生する限り、MySQLで望ましい結果を生成します。

tickとrefidのすべてのペアを生成するクエリから始めます。次の例では、テーブルを使用してペアを生成しています。そのため、基になるテーブルにティックが表示されない場合は、生成されたペアにティックも表示されません。 refidsには同じことが当てはまりますが、「すべてのrefidsはtick = 1で値を持つ」という制限は、後者が決して起こらないようにする必要があります。これを使用する

SELECT tick, refid FROM 
    (SELECT refid FROM chadwick WHERE tick=1) AS r 
    JOIN 
    (SELECT DISTINCT tick FROM chadwick) AS t 

、REFIDにequijoiningとθ がダニに-joiningによってテーブルに存在する最大のダニと一緒に、すべての不足しているダニ、REFIDペアを生成します。生成されたティックごとにグループ分けする。各ペアの1つの行のみが必要であるため、refidする。既存のtick、refidのペアを除外するための鍵はHAVINGです。厳密に言えば、HAVINGを省略することができます。結果のクエリは既存の値を持つ既存の行を返します。サブセレクトとして上記からの選択最終

SELECT tr.tick, tr.refid, MAX(c.tick) AS ctick 
    FROM 
     (SELECT tick, refid FROM 
     (SELECT refid FROM chadwick WHERE tick=1) AS r 
     JOIN 
     (SELECT DISTINCT tick FROM chadwick) AS t 
    ) AS tr 
    JOIN chadwick AS c ON tr.tick >= c.tick AND tr.refid=c.refid 
    GROUP BY tr.tick, tr.refid 
    HAVING tr.tick > MAX(c.tick) 

一つは、所与ctickの値を取得するために、元のテーブルに結合テーブルに新しい行を返します。 (tick, refid)(refid, tick)インデックスと共に試料台に

INSERT INTO chadwick 
SELECT missing.tick, missing.refid, c.value 
    FROM (SELECT tr.tick, tr.refid, MAX(c.tick) AS ctick 
    FROM 
     (SELECT tick, refid FROM 
     (SELECT refid FROM chadwick WHERE tick=1) AS r 
     JOIN 
     (SELECT DISTINCT tick FROM chadwick) AS t 
    ) AS tr 
    JOIN chadwick AS c ON tr.tick >= c.tick AND tr.refid=c.refid 
    GROUP BY tr.tick, tr.refid 
) AS missing 
    JOIN chadwick AS c ON missing.ctick = c.tick AND missing.refid=c.refid 
; 

性能:

+----+-------------+------------+-------+-------------------+----------+---------+----------+------+---------------------------------+ 
| id | select_type | table  | type | possible_keys  | key  | key_len | ref  | rows | Extra       | 
+----+-------------+------------+-------+-------------------+----------+---------+----------+------+---------------------------------+ 
| 1 | PRIMARY  | <derived2> | ALL | NULL    | NULL  | NULL | NULL  | 3 |         | 
| 1 | PRIMARY  | c   | ALL | tick_ref,ref_tick | NULL  | NULL | NULL  | 6 | Using where; Using join buffer | 
| 2 | DERIVED  | <derived3> | ALL | NULL    | NULL  | NULL | NULL  | 9 | Using temporary; Using filesort | 
| 2 | DERIVED  | c   | ref | tick_ref,ref_tick | ref_tick | 5  | tr.refid | 1 | Using where; Using index  | 
| 3 | DERIVED  | <derived4> | ALL | NULL    | NULL  | NULL | NULL  | 3 |         | 
| 3 | DERIVED  | <derived5> | ALL | NULL    | NULL  | NULL | NULL  | 3 | Using join buffer    | 
| 5 | DERIVED  | chadwick | index | NULL    | tick_ref | 10  | NULL  | 6 | Using index      | 
| 4 | DERIVED  | chadwick | ref | tick_ref   | tick_ref | 5  |   | 2 | Using where; Using index  | 
+----+-------------+------------+-------+-------------------+----------+---------+----------+------+---------------------------------+

Iが言ったように、あまりにも多くのサブ選択します。一時的なテーブルが問題を助けるかもしれません。

欠落ダニをチェックする:

SELECT clo.tick+1 AS missing_tick 
    FROM chadwick AS chi 
    RIGHT JOIN chadwick AS clo ON chi.tick = clo.tick+1 
    WHERE chi.tick IS NULL; 

これは1 +テーブル内の最大目盛りに等しいティックと少なくとも一つの列を返します。したがって、この結果の最大値は無視できます。

関連する問題