w3schools minus ejemplo all tsql

tsql - minus - union all mysql



¿Por qué EXCEPT existe en T-SQL? (4)

Acabo de leer sobre EXCEPTO e INTERSECT en MSDN Library y encontré este ejemplo de cómo usar INTERSECT:

USE AdventureWorks2008R2 GO SELECT ProductID FROM Production.Product INTERSECT SELECT ProductID FROM Production.WorkOrder ; --Result: 238 Rows (products that have work orders)

Quizás esté pasado de moda, pero normalmente usaría el siguiente código para lograr el mismo resultado:

SELECT P.ProductID FROM Production.Product P INNER JOIN Production.WorkOrder W ON W.ProductID = P.ProductID

¿Me estoy perdiendo algo, o es INTERSECT lo mismo que INNER JOIN? ¿Hay un beneficio de rendimiento al usar uno sobre el otro?

La misma pregunta por EXCEPTO. Cómo es esto:

USE AdventureWorks2008R2; GO SELECT ProductID FROM Production.Product EXCEPT SELECT ProductID FROM Production.WorkOrder ; --Result: 266 Rows (products without work orders)

diferente de esto:

SELECT P.ProductID FROM Production.Product P LEFT JOIN Production.WorkOrder W ON W.ProductID = P.ProductID WHERE W.ProductID IS NULL

?


En mi opinión, EXCEPT e INTERSECT se utilizan para hacer las mismas cosas que el comando JOIN, pero es más simple con tablas que no tienen claves primarias, por ejemplo:

con INTERSECT :

SELECT FIRSTNAME, LASTNAME, ADDRESSLINE1, CITY, STATEPROVINCECODE, POSTALCODE FROM MANAGER EXCEPT SELECT FIRSTNAME, LASTNAME, ADDRESSLINE1, CITY, STATEPROVINCECODE, POSTALCODE FROM CUSTOMER

Y para tener los mismos resultados con JOIN, debes hacer:

SELECT M.FIRSTNAME, M.LASTNAME, M.ADDRESSLINE1, M.CITY, M.STATEPROVINCECODE, M.POSTALCODE FROM MANAGER M WHERE NOT EXISTS (SELECT * FROM CUSTOMER C WHERE M.FIRSTNAME = C.FIRSTNAME AND M.LASTNAME = C.LASTNAME AND M.ADDRESSLINE1 = C.ADDRESSLINE1 AND M.CITY = C.CITY AND M.POSTALCODE = C.POSTALCODE) GROUP BY M.FIRSTNAME,M.LASTNAME,M.ADDRESSLINE1,M.CITY, M.STATEPROVINCECODE,M.POSTALCODE

Más información here .


Me centraré en EXCEPT solo porque estoy más familiarizado con él. Además, como descargo de responsabilidad, mis ejemplos estarán en Sqlite, ya que estoy en una caja de Linux. Sin embargo, tanto Sqlite como SQL Server deberían admitir la funcionalidad.

Tanto INTERSECT como EXCEPT son operadores de conjuntos, derivados de las ideas subyacentes en el álgebra relacional . Operan en valores distintos , siendo operadores establecidos.

Tu ejemplo es simplista. Daré un contraejemplo, usando una versión de Sqlite de la base de datos de ejemplo de Northwind .

Digamos que desea obtener los CustomerID de todos los clientes que hicieron un pedido con EmployeeID de 5, pero NO aquellos que también hicieron un pedido con EmployeeID de 6. Esto es simple y natural con un EXCEPT .

SELECT CustomerID FROM orders WHERE EmployeeID = 5 EXCEPT SELECT CustomerID FROM orders WHERE EmployeeID = 6

Esto devuelve 14 filas en mi versión de Northwind.

Supongamos que decide reescribir esto utilizando JOIN s. Tal vez algo como esto?

SELECT o1.CustomerID FROM orders o1 INNER JOIN orders o2 ON o1.CustomerID = o2.CustomerID WHERE o1.EmployeeID = 5 AND o2.EmployeeID != 6

Whoops, 525 filas. Tal vez agregar un DISTINCT ?

SELECT DISTINCT o1.CustomerID FROM orders o1 INNER JOIN orders o2 ON o1.CustomerID = o2.CustomerID WHERE o1.EmployeeID = 5 AND o2.EmployeeID != 6

Ahora son 28 filas, aún mucho más de lo que obtuvimos EXCEPT . La razón es que esto no elimina los CustomerID que han realizado un pedido con 6. En su lugar, devuelve todos los CustomerID que tienen un pedido con 5 y algún EmployeeID distinto de 6, ya sea que tengan un pedido con EmployeeID 6 o no.

En resumen, EXCEPT e INTERSECT son operadores de conjuntos que comparan dos consultas, devuelven tuplas únicas y ciertamente tienen su uso.


Sus ejemplos de sus consultas "equivalentes" son incorrectos: la consulta con INTERSECT no siempre devuelve el mismo resultado que INNER JOIN y el mismo para EXCEPT y LEFT JOIN .

Mira el ejemplo particular sobre INTERSECT:

DECLARE @t TABLE(t INT NOT NULL) DECLARE @x TABLE(x INT NOT NULL) INSERT @t VALUES (1), (2), (3) INSERT @x VALUES(1), (1), (1) SELECT t FROM @t INTERSECT SELECT x FROM @x SELECT t FROM @t INNER JOIN @x ON x = t

INTERSECT es más parecido ( pero no igual ) a la cláusula IN :

SELECT t FROM @t WHERE t IN (select x FROM @x)

o como EXISTS

SELECT t FROM @t WHERE EXISTS (select * FROM @x WHERE x = t)

Los mismos ejemplos se pueden adaptar a la cláusula EXCEPT .


  • INTERSECT y EXCEPT son semi-joins
  • JOIN es equi-join

Así que cuando unes 2 tablas que coinciden, digamos, 5 filas y 3 filas

  • UNIR da 15 filas
  • INTERSECT da 3 filas

EXCEPTO es similar a OUTER JOIN por el mismo motivo

Mientras estamos hablando de semi-uniones, entonces en su mayoría

  • INTERSECT da los mismos resultados que EXISTS.
  • EXCEPTO da los mismos resultados que NO EXISTE

La "mayoría" viene porque INTERSECT y EXCEPTO

Edición, demostración rápida de todo esto.

DECLARE @t1 TABLE (t1col INT); INSERT @t1 VALUES (1), (2), (2), (3), (3), (5), (5); DECLARE @t2 TABLE (t2col INT); INSERT @t2 VALUES (1), (2), (3), (4); SELECT ''INNER JOIN'', * FROM @t1 t1 JOIN @t2 t2 ON t1.t1col = t2.t2col -- same both ways SELECT ''t1 INTERSECT t2'', * FROM @t1 INTERSECT SELECT ''t1 INTERSECT t2'', * FROM @t2; SELECT ''t2 INTERSECT t1'', * FROM @t2 INTERSECT SELECT ''t2 INTERSECT t1'', * FROM @t1; SELECT ''t1 EXISTS t2'', * FROM @t1 t1 WHERE EXISTS (SELECT * FROM @t2 t2 WHERE t1.t1col = t2.t2col); SELECT ''t2 EXISTS t1'', * FROM @t2 t2 WHERE EXISTS (SELECT * FROM @t1 t1 WHERE t1.t1col = t2.t2col); SELECT ''t1 LEFT JOIN t2, IS NULL'', * FROM @t1 t1 LEFT JOIN @t2 t2 ON t1.t1col = t2.t2col WHERE t2.t2col IS NULL SELECT ''t2 LEFT JOIN t1, IS NULL'', * FROM @t2 t2 LEFT JOIN @t1 t1 ON t1.t1col = t2.t2col WHERE t1.t1col IS NULL SELECT ''t1 EXCEPT t2'', * FROM @t1 EXCEPT SELECT ''t1 EXCEPT t2'', * FROM @t2; SELECT ''t2 EXCEPT t1'', * FROM @t2 EXCEPT SELECT ''t2 EXCEPT t1'', * FROM @t1; SELECT ''t1 NOT EXISTS t2'', * FROM @t1 t1 WHERE NOT EXISTS (SELECT * FROM @t2 t2 WHERE t1.t1col = t2.t2col); SELECT ''t2 NOT EXISTS t1'', * FROM @t2 t2 WHERE NOT EXISTS (SELECT * FROM @t1 t1 WHERE t1.t1col = t2.t2col);

Actualización: febrero de 2013. Se agregó una columna adicional para describir la operación.