6

次の Table1 が与えられた場合:

    RefID  intVal  SomeVal
    ----------------------
        1      10    val01
        1      20    val02
        1      30    val03
        1      40    val04
        1      50    val05
        2      10    val06
        2      20    val07
        2      30    val08
        2      40    val09
        2      50    val10
        3      12    val11
        3      14    val12
        4      10    val13
        5     100    val14
        5     150    val15
        5    1000    val16

いくつかの RefID と intVals を含む Table2

    RefID  intVal
    -------------
        1      11    
        1      28    
        2       9    
        2      50    
        2      51    
        4      11    
        5       1    
        5     150    
        5     151    

各 RefID に対して次に大きい intValue を取得するには SQL ステートメントが必要であり、Table1 に見つからない場合は NULL が必要です。次の結果が期待されます。

    RefID  intVal  nextGt  SomeVal 
    ------------------------------
        1      11      20  val01
        1      28      30  val03
        2       9      10  val06
        2      50      50  val10
        2      51    NULL   NULL
        4      11    NULL   NULL
        5       1     100  val14
        5     150     150  val15
        5     151    1000  val16

助けていただければ幸いです!

4

3 に答える 3

10

派生テーブルは、指定されたtable1およびtable2aから最小値を取得します。外部クエリはsomeValueのみを取得します。refidintVal

select a.refid, a.intVal, a.nextGt, table1.SomeVal
from
(
    select table2.refid, table2.intval, min (table1.intVal) nextGt
      from table2
      left join table1
        on table2.refid = table1.refid
       and table2.intVal <= table1.intVal
     group by table2.refid, table2.intval
) a
-- table1 is joined again to retrieve SomeVal 
left join table1
  on a.refid = table1.refid
 and a.nextGt = table1.intVal

これがライブテスト付きのSQLフィドルです。

于 2012-05-24T11:52:00.333 に答える
3

ROW_NUMBER()関数を使用してこれを解決できます。

SELECT
  RefID,
  intVal,
  NextGt,
  SomeVal,
FROM
  (
    SELECT
      t2.RefID,
      t2.intVal,
      t1.intVal AS NextGt,
      t1.SomeVal,
      ROW_NUMBER() OVER (PARTITION BY t2.RefID, t2.intVal ORDER BY t1.intVal) AS rn
    FROM
      dbo.Table2 AS t2
      LEFT JOIN dbo.Table1 AS t1 ON t1.RefID = t2.RefID AND t1.intVal >= t2.intVal
  ) s
WHERE
  rn = 1
;

派生テーブルは、各行を、同じおよびより大きいか等しい をTable2持つすべての行と照合します。一致の各サブセットがランク付けされ、最初の行がメイン クエリによって返されます。Table1RefIDintValTable2.intVal

ネストされたクエリは外部結合を使用するため、一致Table2しない行Table1が引き続き返されます (列が null に置き換えられTable1ます)。

または、次を使用できますOUTER APPLY

SELECT
  t2.RefID,
  t2.intVal,
  t1.intVal AS NextGt,
  t1.SomeVal
FROM
  dbo.Table2 AS t2
  OUTER APPLY
  (
    SELECT TOP (1)
      t1.intVal
    FROM
      dbo.Table1 AS t1
    WHERE
      t1.RefID = t2.RefID
      AND t1.intVal >= t2.intVal
    ORDER BY
      t1.intVal ASC
  ) AS t1
;

この方法は間違いなくより簡単です:Table2各行に対して、同じ条件セットに基づいて からすべての一致を取得しTable1、一致を の昇順で並べ替え、Table1.intVal最上位の を取得しintValます。

于 2012-05-24T12:00:55.550 に答える
0

これは、join、group by、case ステートメント、およびトリックを使用して実行できます。

select t1.refid, t2.intval,
       min(case when t1.intval > t2.intval then t1.intval end) as min_greater_than_ref,
       substring(min(case when t1.intval > t2.intval
                          then right('00000000'+cast(t1.intval as varchar(255)), 8)+t1.SomeVal)
                     end)), 9, 1000)
from table1 t1 left join
     table2 t2
     on t1.refid = t2.refid
group by t1.refid, t2.intval 

SO、秘訣は、整数値を SomeValue の先頭に追加し、整数値をゼロで埋めます (この場合は 8 文字まで)。「00000020val01」のようなものが得られます。この列の最小値は、整数の最小値に基づいています。最後のステップは、値を抽出することです。

この例では、連結に SQL Server 構文を使用しました。他のデータベースでは、CONCAT() または || を使用する場合があります。

于 2012-05-24T13:34:04.750 に答える