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)"?
Ответы
Ответ 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