Вопрос о группировке T-SQL - PullRequest
0 голосов
/ 19 мая 2009

Время от времени у меня возникает такой сценарий, и я никогда не могу придумать наиболее эффективный запрос для получения информации:

Допустим, у нас есть таблица с тремя столбцами (A int, B int, C int). Мой запрос должен ответить на такой вопрос: «Скажите, каково значение столбца C для наибольшего значения столбца B, где A = 5.» Реальный сценарий для чего-то подобного: «A» - это ваши пользователи, «B» - это дата, когда что-то произошло, и «C» - это значение, где вы хотите получить самую последнюю запись для определенного пользователя.

Я всегда получаю такой запрос:

SELECT
    C
FROM
    MyTable
WHERE
    A = 5
    AND B = (SELECT MAX(B) FROM MyTable WHERE A = 5)

Чего мне не хватает, чтобы сделать это в одном запросе (в отличие от их вложения)? Что-то вроде «Наличие»?

Ответы [ 5 ]

4 голосов
/ 19 мая 2009

Ответ BoSchatzberg работает, когда вам важен только 1 результат, где A = 5. Но я подозреваю, что этот вопрос является результатом более общего случая. Что если вы хотите перечислить верхнюю запись для каждого отдельного значения A?

SELECT t1.*
FROM MyTable t1
   INNER JOIN 
     (
       SELECT A, MAX(B)
       FROM MyTable
       GROUP BY A
     )  t2 ON t1.A = t2.A AND t1.B = t2.B
2 голосов
/ 19 мая 2009
--
SELECT C
FROM MyTable
INNER JOIN (SELECT A, MAX(B) AS MAX_B FROM MyTable GROUP BY A) AS X
    ON MyTable.A = X.A
    AND MyTable.B = MAX_B
--
WHERE MyTable.A = 5

В этом случае первый раздел (между комментариями) также можно легко переместить в представление для модульности или повторного использования.

2 голосов
/ 19 мая 2009

Вы можете сделать это:

SELECT TOP 1 C
FROM    MyTable
WHERE    A = 5
ORDER BY b DESC
1 голос
/ 19 мая 2009

Я думаю, что вы близки (и то, что у вас будет работать). Вы можете использовать что-то вроде следующего:

select C
     , max(B)
  from MyTable
 where A = 5
group by C
0 голосов
/ 19 мая 2009

После небольшого тестирования я не думаю, что это можно сделать, не выполнив то, что вы уже делаете (то есть подзапрос). Поскольку вам нужно максимальное значение B, и вы не можете получить значение C, не включив его в предложение GROUP BY или HAVING, подзапрос кажется наилучшим способом.

    create table #tempints (
    a int,
    b int,
    c int
    )

    insert into #tempints values (1, 8, 10)
    insert into #tempints values (1, 8, 10)
    insert into #tempints values (2, 4, 10)
    insert into #tempints values (5, 8, 10)
    insert into #tempints values (5, 3, 10)
    insert into #tempints values (5, 7, 10)
    insert into #tempints values (5, 8, 15)

    /* this errors out with "Column '#tempints.c' is invalid in the select list because it is not contained in either an 
    aggregate function or the GROUP BY clause." */
    select t1.c, max(t1.b)
    from #tempints t1
    where t1.a=5 

    /* this errors with "An aggregate may not appear in the WHERE clause unless it is in a subquery contained in a HAVING 
    clause or a select list, and the column being aggregated is an outer reference." */
    select t1.c, max(t1.b)
    from #tempints t1, #tempints t2
    where t1.a=5 and t2.b=max(t1.b)

    /* errors with "Column '#tempints.a' is invalid in the HAVING clause because it is not contained in either an aggregate 
function or the GROUP BY clause." */
    select c
    from #tempints
    group by b, c
    having a=5 and b=max(b)

    drop table #tempints
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...