Usaré un ejemplo concreto pero hipotético.
Cada pedido normalmente tiene solo una línea de pedido :
Pedidos:
OrderGUID OrderNumber
========= ============
{FFB2...} STL-7442-1
{3EC6...} MPT-9931-8A
Artículos de línea:
LineItemGUID Order ID Quantity Description
============ ======== ======== =================================
{098FBE3...} 1 7 prefabulated amulite
{1609B09...} 2 32 spurving bearing
Pero ocasionalmente habrá un pedido con dos líneas de pedido:
LineItemID Order ID Quantity Description
========== ======== ======== =================================
{A58A1...} 6,784,329 5 pentametric fan
{0E9BC...} 6,784,329 5 differential girdlespring
Normalmente al mostrar los pedidos al usuario:
SELECT Orders.OrderNumber, LineItems.Quantity, LineItems.Description
FROM Orders
INNER JOIN LineItems
ON Orders.OrderID = LineItems.OrderID
Quiero mostrar el artículo único en el pedido. Sin embargo, con este orden de vez en cuando, con dos (o más) elementos, las órdenes se parecen ser duplicada :
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
Lo que realmente quiero es que SQL Server solo elija uno , ya que será lo suficientemente bueno :
OrderNumber Quantity Description
=========== ======== ====================
STL-7442-1 7 prefabulated amulite
MPT-9931-8A 32 differential girdlespring
KSG-0619-81 5 panametric fan
Si me vuelvo aventurero, podría mostrarle al usuario una elipsis para indicar que hay más de uno:
OrderNumber Quantity Description
=========== ======== ====================
STL-7442-1 7 prefabulated amulite
MPT-9931-8A 32 differential girdlespring
KSG-0619-81 5 panametric fan, ...
Entonces la pregunta es cómo
- eliminar filas "duplicadas"
- solo unirse a una de las filas, para evitar duplicaciones
Primer intento
Mi primer intento ingenuo fue unirme solo a las líneas de pedido " 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
Pero eso da el error:
La columna o prefijo 'Pedidos' no
coincide con un nombre de tabla o nombre de alias
utilizado en la consulta.
Presumiblemente porque la selección interna no ve la tabla externa.
fuente
group by
?group by
requeriría enumerar todas las otras columnas, excluyendo la que no desea duplicados. FuenteRespuestas:
En SQL Server 2005 y versiones posteriores, simplemente puede reemplazar
INNER JOIN
conCROSS APPLY
:Tenga en cuenta que
TOP 1
sinORDER BY
no es determinista: esta consulta le dará una línea de pedido por pedido, pero no está definido cuál será.Las invocaciones múltiples de la consulta pueden proporcionarle diferentes líneas de pedido para el mismo pedido, incluso si el subyacente no cambió.
Si desea un orden determinista, debe agregar una
ORDER BY
cláusula a la consulta más interna.fuente
CROSS APPLY
en su lugarINNER JOIN
yOUTER APPLY
en su lugarLEFT JOIN
(lo mismo queLEFT OUTER JOIN
).Sé que esta pregunta fue respondida hace un tiempo, pero cuando se trata de grandes conjuntos de datos, las consultas anidadas pueden ser costosas. Aquí hay una solución diferente donde la consulta anidada solo se ejecutará una vez, en lugar de por cada fila devuelta.
fuente
Podrías hacerlo:
Esto requiere un índice (o clave principal) activado
LineItems.LineItemID
y un índice activadoLineItems.OrderID
o será lento.fuente
LineItems.LineItemID = null
y elimina completamente los pedidos de la entidad izquierda del resultado.La respuesta de @Quassnoi es buena, en algunos casos (especialmente si la tabla externa es grande), una consulta más eficiente podría ser el uso de funciones de ventana, como esta:
A veces solo necesita probar qué consulta proporciona un mejor rendimiento.
fuente
Otro enfoque que utiliza la expresión de tabla común:
o, al final, tal vez le gustaría mostrar todas las filas unidas?
versión separada por comas aquí:
fuente
Desde SQL Server 2012 y en adelante, creo que esto funcionará:
fuente
Las subconsultas correlacionadas son subconsultas que dependen de la consulta externa. Es como un bucle for en SQL. La subconsulta se ejecutará una vez para cada fila en la consulta externa:
fuente
EDITAR: no importa, Quassnoi tiene una mejor respuesta.
Para SQL2K, algo como esto:
fuente
Mi forma favorita de ejecutar esta consulta es con una cláusula no existe. Creo que esta es la forma más eficiente de ejecutar este tipo de consulta:
Pero no he probado este método contra otros métodos sugeridos aquí.
fuente
Probé la cruz, funciona bien, pero lleva un poco más de tiempo. Columnas de línea ajustadas para tener un grupo máximo y agregado que mantuvo la velocidad y eliminó el registro adicional.
Aquí está la consulta ajustada:
fuente
prueba esto
fuente