T-SQL questão agrupamento

votos
0

De vez em quando eu tenho um cenário como este, e nunca pode vir até com a consulta mais eficiente para puxar as informações:

Vamos dizer que temos uma tabela com três colunas (A, int B, C int). Minha consulta precisa responder a uma pergunta como esta: Diga-me qual é o valor da coluna C é para o maior valor da coluna B, onde A = 5. Um cenário do mundo real para algo como isso seria 'A' é seus usuários, 'b' é a data algo aconteceu, e 'C' é o valor, onde você deseja que a entrada mais recente para um usuário específico.

Eu sempre acabo com uma consulta como esta:

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

O que estou ausente para fazer isso em uma única consulta (oposição a nidificação eles)? Algum tipo de cláusula de 'ter'?

Publicado 19/05/2009 em 20:20
fonte usuário
Em outras línguas...                            


5 respostas

votos
4

A resposta de BoSchatzberg funciona quando você só se preocupam com o resultado 1, onde A = 5. Mas eu suspeito que esta questão é o resultado de um caso mais geral. E se você deseja listar o registro superior para cada valor distinto de 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
Respondeu 19/05/2009 em 20:36
fonte usuário

votos
2
--
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

Neste caso, a primeira secção (entre os comentários) pode também facilmente ser movidos para uma vista para modular ou reutilização.

Respondeu 19/05/2009 em 20:38
fonte usuário

votos
2

Você consegue fazer isso:

SELECT TOP 1 C
FROM    MyTable
WHERE    A = 5
ORDER BY b DESC
Respondeu 19/05/2009 em 20:34
fonte usuário

votos
1

Eu acho que você está perto (e que você tem que trabalhar). Você pode usar algo como o seguinte:

select C
     , max(B)
  from MyTable
 where A = 5
group by C
Respondeu 19/05/2009 em 20:25
fonte usuário

votos
-1

Depois de um pouco de testes, eu não acho que isso pode ser feito sem fazê-lo da maneira que você já está fazendo isso (ou seja, uma subconsulta). Desde que você precisa do máximo de B e você não pode obter o valor de C sem incluir igualmente que, em um GROUP BY ou HAVING cláusula, uma subconsulta parece ser o melhor caminho.

    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
Respondeu 19/05/2009 em 20:31
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more