web-dev-qa-db-ja.com

T-SQL:MAX(その他の列)に基づいて列を選択

サブクエリを使用せずにこれを行う簡単な方法があることを願っています:

シナリオ:「キー」、「サブキー」、および「値」の列を持つ「TableA」があります。特定の「キー」のMAX(「サブキー」)の「値」を取得する必要があります。

したがって、テーブルに行が含まれている場合:

KEY SUBKEY VALUE
1   1      100
1   2      200
1   3      300

Key = 1の場合、値300が必要です。次のようなことを望んでいました。

SELECT
  VALUE
FROM
  TableA
WHERE
  Key = 1
HAVING
  SubKey = MAX(SubKey)

しかし、それは禁止です。 「WHERE SubKey =(subselect for max subkey)」を実行せずにこれを行う方法はありますか?

33
John

自己結合の使用:

これは、複数ある場合に一致するサブキー値を持つすべての値を返します。

SELECT a.value
  FROM TABLE a
  JOIN (SELECT MAX(t.subkey) AS max_subkey
          FROM TABLE t
         WHERE t.key = 1) b ON b.max_subkey = a.subkey
 WHERE a.key = 1

RANKおよびCTEの使用(SQL Server 2005+):

これは、複数ある場合に一致するサブキー値を持つすべての値を返します。

WITH summary AS (
  SELECT t.*,
         RANK() OVER(ORDER BY t.subkey DESC) AS rank
    FROM TABLE t
   WHERE t.key = 1)
SELECT s.value
  FROM summary s
 WHERE s.rank = 1

ROW_NUMBERとCTEの使用(SQL Server 2005+):

同じサブキー値を持つ複数の行がある場合でも、これは1行を返します...

WITH summary AS (
  SELECT t.*,
         ROW_NUMBER() OVER(ORDER BY t.subkey DESC) AS rank
    FROM TABLE t
   WHERE t.key = 1)
SELECT s.value
  FROM summary s
 WHERE s.rank = 1

TOPを使用:

同じサブキー値を持つ複数の行がある場合でも、これは1行を返します...

  SELECT TOP 1
         t.value
    FROM TABLE t
   WHERE t.key = 1
ORDER BY t.subkey DESC
54
OMG Ponies

非常にシンプル、結合、サブクエリなし:

SELECT FIRST_VALUE(Value) OVER (ORDER BY SubKey DESC)
FROM TableA
WHERE Key = 1

各キーの最大値が必要な場合:

SELECT DISTINCT Key, 
FIRST_VALUE(Value) OVER (PARTITION BY Key ORDER BY SubKey DESC)
FROM TableA
19
SELECT MAX(Value)
FROM TableA t1
GROUP BY Key, SubKey
HAVING SubKey = (SELECT MAX(SubKey) FROM TableA t2 WHERE t1.Key = t2.Key)
  AND Key = 1
4
Amy B

OMGポニーは、ほとんどの方法でそれを実現します。ここにもう1つあります。

SELECT
    T1.value
FROM
    My_Table T1
LEFT OUTER JOIN My_Table T2 ON
    T2.key = T1.key AND
    T2.subkey > T1.subkey
WHERE
    T2.key IS NULL

T2.keyがNULLになるのは、LEFT JOINに一致するものがないときだけです。これは、より高いサブキーを持つ行が存在しないことを意味します。同じ(最上位の)サブキーを持つ行が複数ある場合、これは複数の行を返します。

3
Tom H

OMGポニーROW_NUMBERメソッドは、同じ量の2つのMAX値が予想より多くのレコードを返し、フィードされている可能性のある挿入を壊す場合に失敗しないため、すべてのシナリオで最適に機能するメソッドです。それによってrecordset

不足していることの1つは、複数のキーも存在する場合に、各最大値に関連付けられたサブキーを返す必要がある場合にそれを行う方法です。 summaryテーブルをMINGROUPの「自分自身」と結合するだけです。

WITH summary AS (
  SELECT t.*,
         ROW_NUMBER() OVER(ORDER BY t.subkey DESC) AS rank
    FROM TABLE t
   WHERE t.key = 1)
SELECT s.*
  FROM summary s
  join  (select key, min(rank) as rank
        from summary
        group by key) sMAX
        on s.key = sMAX.key and r.rank = sMAX.rank
1
Diego

一度に多数のキーに対する回答ではなく、常に1つのキー値に対して1つの行のみが必要な場合、すべての結合は無駄になります。 OMG Poniesが既に提供したTOP 1クエリを使用してください。

0
ErikE

CTEを使用する複数のキーの場合:

WITH CTE AS
(
    SELECT key1, key2, MAX(subkey) AS MaxSubkey
    FROM TableA 
    GROUP BY key1, key2
)
SELECT a.Key1, a.Key2, a.Value
FROM TableA a
    INNER JOIN CTE ON a.key1 = CTE.key1 AND a.key2 = CTE.key2 AND
                      a.subkey = CTE.MaxSubkey
0
Glen