Подтвердить что ты не робот

T-SQL: выбор столбца на основе MAX (другой столбец)

Я надеюсь, что есть простой способ сделать это, не используя подзапрос:

Сценарий: у вас есть "TableA" с столбцами "Key", "SubKey" и "Value". Мне нужно получить "значение" MAX ( "SubKey" ) для данного "ключа".

Итак, если в таблице были строки:

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)"?

4b9b3361

Ответ 1

Использование самосоединения:

Это вернет все значения со значениями подключений, которые соответствуют, в случае, если есть кратные.

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 +):

Это вернет одну строку, даже если есть более одного с тем же значением подраздела...

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:

Это вернет одну строку, даже если есть более одного с тем же значением подраздела...

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

Ответ 2

Очень просто, нет соединения, нет подзапроса:

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

Ответ 3

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

OMG Ponies поразил большинство способов сделать это. Здесь еще один:

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 нет совпадения, что означает, что ни одна строка не существует с более высоким подразделением. Это приведет к возврату нескольких строк, если имеется несколько строк с тем же самым (самым высоким) подразделом.

Ответ 5

OMG Ponie ROW_NUMBER метод - тот, который будет работать лучше всего во всех сценариях, так как он не сбой в случае наличия двух значений MAX с то же количество возвращает больше записей, чем ожидалось, и ломает возможную вставку, которую вы могли бы получить от этого recordset.

Одна вещь, которая отсутствует, заключается в том, как это сделать в случае необходимости вернуть подраздел, связанный с каждым максимальным значением, когда есть также несколько ключей. Просто присоединитесь к таблице summary с помощью MIN и GROUP "самого себя" и отпустите.

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

Ответ 6

Если вы всегда хотите только одну строку для одного ключевого значения, а не ответ для многих ключей одновременно, все элементы соединения бесполезны надстройки. Просто используйте ТОП-1 запрос, который OMG Ponies уже дал вам.

Ответ 7

В случае использования нескольких клавиш с помощью 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