INTERSECT
EXCEPT
ALL
ANY
ALL y ANY no son nuevos, pero INTERSECT y EXCEPT son nuevos.
INTERSECT, EXCEPT and UNION
Para experimentar con esos comandos David decidió ver dos conjuntos de valores para CustomerID.Customers (Clientes) en sales territory 10 (United Kingdom)
(pedidos) Sales orders de July 2004, el cual es el último mes de pedidos en Adventureworks
La mejor manera de ver que hacen estos dos comandos es comparar los datos en los diagramas.
Diferentes formas de escribir un query con EXCEPT.
Si bien nunca usé EXCEPT antes yo he obtenido los mismos resultados por métodos tradicionales, hay muchas formas de hacer lo mismo, por ejemplo:
LEFT JOIN
Este query trae los resultados requeridos.
SELECT C.CustomerID FROM Sales.Customer AS C LEFT JOIN Sales.SalesOrderHeader AS OH ON C.CustomerID = OH.CustomerID AND OrderDate>='2004-07-01' WHERE OH.CustomerID IS NULL AND C.TerritoryID=10WHERE CustomerID NOT IN(…)
Buscando la eficiencia, otra forma de hacer lo mismo. SELECT CustomerID FROM Sales.Customer WHERE TerritoryID=10 AND CustomerID NOT IN( SELECT customerid FROM Sales.SalesOrderHeader WHERE OrderDate>='2004-07-01' )
EXCEPT
Finalmente usando el nuevo comando Except.SELECT CustomerID FROM Sales.Customer WHERE TerritoryID=10 EXCEPT SELECT customerid FROM Sales.SalesOrderHeader WHERE OrderDate>='2004-07-01'
Diferentes maneras de escribir un query tipo INTERSECT
Tres ejemplos:
INNER JOIN
Como un cliente puede tener mas de un pedido tengo que hacer una lista con distinct para los valores del customerid, veamos dos enfoques para lo mismo.
As any customer can have more than one order I am going to have to make a distinct list of CustomerID values. I decided to try a couple of approaches.
SELECT DISTINCT C.CustomerID FROM Sales.Customer AS C INNER JOIN Sales.SalesOrderHeader AS OH ON C.CustomerID = OH.CustomerID WHERE C.TerritoryID=10 AND OH.OrderDate>='2004-07-01' SELECT C.CustomerID FROM Sales.Customer AS C INNER JOIN (SELECT DISTINCT CustomerID FROM Sales.SalesOrderHeader WHERE OrderDate>='2004-07-01' )AS OH ON C.CustomerID = OH.CustomerID WHERE C.TerritoryID=10WHERE CustomerID IN(…)
SELECT CustomerID FROM Sales.Customer WHERE TerritoryID=10 AND CustomerID IN( SELECT customerid FROM Sales.SalesOrderHeader WHERE OrderDate>='2004-07-01' )
INTERSECT
Finalmente un intersect.SELECT CustomerID FROM Sales.Customer WHERE TerritoryID=10 INTERSECT SELECT customerid FROM Sales.SalesOrderHeader WHERE OrderDate>='2004-07-01'The ANY and ALL Predicate
ANY and ALL are predicates I have never needed to use.
ANY
Los dos queries nos ofrecen los mismos resultados y el mismo plan de ejecución:SELECT * FROM Sales.SalesPerson WHERE TerritoryID = ANY( SELECT TerritoryID FROM Sales.SalesTerritory WHERE CountryRegionCode='US' ) SELECT * FROM Sales.SalesPerson WHERE TerritoryID IN( SELECT TerritoryID FROM Sales.SalesTerritory WHERE CountryRegionCode='US' )ALL
All permite una comparación contra todos los valores en una lista de un select, por caso estos dos queries son idénticos:
SELECT * FROM Sales.SalesOrderHeader WHERE TotalDue > ALL(SELECT TotalDue FROM Sales.TopSales) ORDER BY Sales.TotalDue DESC SELECT * FROM Sales.SalesOrderHeader WHERE TotalDue > (SELECT MAX(TotalDue) FROM Sales.TopSales) ORDER BY Sales.TotalDue DESCLa página original se encuentra en:
http://www.sqlservercentral.com/articles/T-SQL/67545/
Hugo Román Bernachea
Mail de contacto: SQLServer777@gmail.com
Microsoft Certified DBA
Microsoft Certified Trainer
Twitter: @bernachea
1 comentarios:
hola
tengo un problema con except
no puedo hacer que me devuelva las tuplas que quiero.
el problema es que le entrego como tabla otra subconsulta (al lado izquierdo y derecho) y cuando trata de entregar la información busca las tablas que estan dentro de la subconsulta y toma como tabla, valga la redundancia, la misma subconsulta.
Aqui va la query
select *
from (SELECT PTRALIN.ITEMS, SUM(CAST (PTRALIN.VALORNETO AS BIGINT )) AS SUMA
FROM (SELECT PTRAL.SUBTITULO+PTRAL.ITEM+PTRAL.ASIGNACION AS ITEMS, *
FROM indapRegion8.DBO.TEStptralin AS PTRAL) AS PTRALIN
WHERE PTRALIN.CODTRAN='AE' AND PTRALIN.ITEMS!=0
GROUP BY PTRALIN.ITEMS) as z
except
select *
from (SELECT PTR_IN.ITEMS, PTR_AE.AE+PTR_IN.ING AS SUMA
FROM (SELECT PTRALIN.ITEMS, SUM(CAST (PTRALIN.VALORNETO AS BIGINT )) AS ING
FROM (SELECT PTRAL.SUBTITULO+PTRAL.ITEM+PTRAL.ASIGNACION AS ITEMS, *
FROM indapRegion8.DBO.TEStptralin AS PTRAL) AS PTRALIN
WHERE PTRALIN.CODTRAN='IN' AND PTRALIN.ITEMS!=0
GROUP BY PTRALIN.ITEMS) AS PTR_IN
JOIN (SELECT PTRALIN.ITEMS, SUM(CAST (PTRALIN.VALORNETO AS BIGINT )) AS AE
FROM (SELECT PTRAL.SUBTITULO+PTRAL.ITEM+PTRAL.ASIGNACION AS ITEMS, *
FROM indapRegion8.DBO.TEStptralin AS PTRAL) AS PTRALIN
WHERE PTRALIN.CODTRAN='AE' AND PTRALIN.NUMEGRESO!='NULL' AND PTRALIN.ITEMS!=0
GROUP BY PTRALIN.ITEMS) AS PTR_AE
ON PTR_AE.ITEMS=PTR_IN.ITEMS) as y
no se que otro operador utilizar en estos casos, porque lo que deseo es que me devuelva los datos de la tabla izquierda pero que no se encuentran en la tabla derecha.
Publicar un comentario