Gostaria de saber se seria possível usar over (partition by...)
cláusula para evitar o uso de uma sub-seleção no exemplo abaixo:
declare @t table (
id int
,code char(2)
,descriptor int
)
insert into @t
select 1, 'a1', 10
union select 1, 'a1', 20
union select 1, 'a1', 30
union select 2, 'b1', 10
union select 2, 'b1', 20
union select 2, 'b1', 30
union select 2, 'b2', 10
union select 2, 'b2', 20
union select 2, 'b2', 30
union select 3, 'c4', 10
union select 3, 'c4', 20
union select 3, 'c4', 30
union select 3, 'c7', 10
union select 3, 'c7', 20
union select 3, 'c7', 30
select *
from @t as t
where code = (select min(code) from @t where id = t.id)
Quero ver apenas os registros com code
igual a a1
, b1
e c4
. Posso over (partition by...)
atribuir 1 a todos aqueles e 2 a códigos b2
e c7
etc, para que no final eu possa dizer where row_number = 1
em vez de usar uma subconsulta?
Sim, mas não com
row_number()
. Você pode usar o agregado da janelamin()
:Ou a
rank()
função da janela (oudense_rank()
aquela, ambas funcionarão da mesma forma para arnk = 1
verificação):Eu estava prestes a comentar que não há como fazer isso sem subconsultas de qualquer tipo (tabelas correlacionadas, derivadas, ctes), mas, infelizmente, existe. Não em 2008R2, mas na versão 2012 usando mais uma função de janela.
Nota: Não use isso. A eficiência provavelmente será pior. A consulta a seguir pode ser boa para um concurso de ofuscação, mas não para produção.
Em vez disso, verifique o bom plano de execução da segunda consulta acima, quando houver um índice adequado.
Apenas por diversão - e horror do futuro mantenedor do código:
Testado no SQLFiddle
Outra maneira (que atende aos requisitos e é compatível com 2005+, mas provavelmente nunca deve ser usada na prática) é
Embora uma resposta divertida (ab)usar
TOP
dessa maneira seja menos eficiente do que simplesmente usar alguma forma de tabela derivada e filtrar noWHERE
entanto.E você não poderá aplicar nenhuma ordem adicional aos resultados dessa consulta sem envolvê-la em uma expressão de tabela. Como a corrente
ORDER BY
deve permanecer inalterada para evitar a alteração dos resultados.SQL Fiddle
Claro que você também pode escrever isso usando um CTE:
Você não pode dizer:
Porque:
Completamente obscuro sobre isso:
Mas talvez quem está rejeitando cegamente a ideia de uma subconsulta não seja sábio o suficiente para reconhecer que uma CTE é apenas uma subconsulta com roupagem diferente. (O fato de muitas pessoas não reconhecerem um CTE à primeira vista é uma bênção e uma maldição às vezes.)
Caso contrário, recomece e explique por que você precisa remover totalmente as subconsultas. Para alguns problemas (como a aplicação de funções de janela), não há alternativa senão filtrá-los em um escopo diferente - o que significa uma subconsulta, tabela derivada, CTE, etc... todos os tipos de uma subconsulta.
A ordem por existe apenas para produzir a tabela de saída na mesma ordem do seu exemplo, mas é totalmente desnecessária.
Revisão para incluir o comentário que adicionei abaixo - manipulação de duplicatas:
Sem subseleções, sem recursos especiais do SQL 2012. Apenas SQL. Pode ser feito.