Vou usar um exemplo concreto, mas hipotético.
Cada pedido normalmente tem apenas um item de linha :
Encomendas:
OrderGUID OrderNumber
========= ============
{FFB2...} STL-7442-1
{3EC6...} MPT-9931-8A
LineItems:
LineItemGUID Order ID Quantity Description
============ ======== ======== =================================
{098FBE3...} 1 7 prefabulated amulite
{1609B09...} 2 32 spurving bearing
Ocasionalmente, porém, haverá um pedido com dois itens de linha:
LineItemID Order ID Quantity Description
========== ======== ======== =================================
{A58A1...} 6,784,329 5 pentametric fan
{0E9BC...} 6,784,329 5 differential girdlespring
Normalmente, ao mostrar os pedidos ao usuário:
SELECT Orders.OrderNumber, LineItems.Quantity, LineItems.Description
FROM Orders
INNER JOIN LineItems
ON Orders.OrderID = LineItems.OrderID
Quero mostrar o único item no pedido. Mas com esta ordem ocasional, contendo dois (ou mais) itens, as ordens que parecem ser duplicados :
OrderNumber Quantity Description
=========== ======== ====================
STL-7442-1 7 prefabulated amulite
MPT-9931-8A 32 spurving bearing
KSG-0619-81 5 panametric fan
KSG-0619-81 5 differential girdlespring
O que eu realmente quero é que o SQL Server escolha apenas um , pois será bom o suficiente :
OrderNumber Quantity Description
=========== ======== ====================
STL-7442-1 7 prefabulated amulite
MPT-9931-8A 32 differential girdlespring
KSG-0619-81 5 panametric fan
Se eu me aventurar, posso mostrar ao usuário uma elipse para indicar que há mais de um:
OrderNumber Quantity Description
=========== ======== ====================
STL-7442-1 7 prefabulated amulite
MPT-9931-8A 32 differential girdlespring
KSG-0619-81 5 panametric fan, ...
Então a questão é como
- eliminar linhas "duplicadas"
- unir-se apenas a uma das linhas, para evitar duplicação
Primeira tentativa
Minha primeira tentativa ingênua foi ingressar apenas nos itens de linha " TOP 1 ":
SELECT Orders.OrderNumber, LineItems.Quantity, LineItems.Description
FROM Orders
INNER JOIN (
SELECT TOP 1 LineItems.Quantity, LineItems.Description
FROM LineItems
WHERE LineItems.OrderID = Orders.OrderID) LineItems2
ON 1=1
Mas isso dá o erro:
A coluna ou o prefixo 'Pedidos' não
corresponde ao nome da tabela ou ao nome alternativo
usado na consulta.
Presumivelmente, porque a seleção interna não vê a tabela externa.
fonte
group by
?group by
exigiria listar todas as outras colunas, excluindo a onde você não deseja duplicatas. FonteRespostas:
No SQL Server 2005 e acima, você pode simplesmente substituir
INNER JOIN
porCROSS APPLY
:Observe que
TOP 1
semORDER BY
não é determinístico: nesta consulta, você receberá um item de linha por pedido, mas não está definido qual será.Várias invocações da consulta podem fornecer itens de linha diferentes para o mesmo pedido, mesmo que o subjacente não tenha sido alterado.
Se você deseja ordem determinística, adicione uma
ORDER BY
cláusula à consulta mais interna.fonte
CROSS APPLY
ao invésINNER JOIN
eOUTER APPLY
em vez dissoLEFT JOIN
(a mesma queLEFT OUTER JOIN
).Sei que essa pergunta foi respondida há um tempo, mas ao lidar com grandes conjuntos de dados, as consultas aninhadas podem ser caras. Aqui está uma solução diferente em que a consulta aninhada será executada apenas uma vez, em vez de para cada linha retornada.
fonte
Você poderia fazer:
Isso requer um índice (ou chave primária) ativado
LineItems.LineItemID
e um índice ativadoLineItems.OrderID
ou será lento.fonte
LineItems.LineItemID = null
e remove completamente os pedidos da entidade esquerda do resultado.A resposta do @Quassnoi é boa, em alguns casos (especialmente se a tabela externa for grande), uma consulta mais eficiente pode ser com o uso de funções em janelas, como esta:
Às vezes, você só precisa testar qual consulta oferece melhor desempenho.
fonte
, Outra abordagem usando a expressão de tabela comum:
ou, no final, talvez você queira mostrar todas as linhas unidas?
versão separada por vírgula aqui:
fonte
Do SQL Server 2012 em diante, acho que isso funcionará:
fonte
Subconsultas correlacionadas são subconsultas que dependem da consulta externa. É como um loop for no SQL. A subconsulta será executada uma vez para cada linha na consulta externa:
fonte
EDIT: deixa pra lá, Quassnoi tem uma resposta melhor.
Para o SQL2K, algo como isto:
fonte
Minha maneira favorita de executar esta consulta é com uma cláusula não existe. Eu acredito que esta é a maneira mais eficiente de executar esse tipo de consulta:
Mas eu não testei esse método contra outros métodos sugeridos aqui.
fonte
Tentei a cruz, funciona bem, mas leva um pouco mais de tempo. Colunas de linhas ajustadas para ter o grupo máximo e adicionado, que manteve a velocidade e reduziu o registro extra.
Aqui está a consulta ajustada:
fonte
tente isso
fonte