sql >> Databáze >  >> RDS >> Database

Operátoři T-SQL SET Část 2:INTERSECT a EXCEPT

Ve svém předchozím článku jsem vysvětlil základy operátorů množin, jejich typy a předpoklady pro jejich použití. Mluvil jsem také o operátorech UNION a UNION ALL, jejich použití a rozdílech.

V tomto článku se naučíme následující:

  1. Operátory EXCEPT a INTERSECT.
  2. Rozdíl mezi INTERSECT a INNER JOIN.
  3. Podrobné vysvětlení INTERSECT a EXCEPT s příkladem.

Operátory EXCEPT a INTERSECT byly zavedeny v SQL Server 2005. Oba jsou množinové operátory používané ke kombinaci sad výsledků generovaných dvěma dotazy a získání požadovaného výstupu.

Co je operátor INTERSECT

INTERSECT se používá k získání záznamů společných pro všechny datové sady načtené z více dotazů nebo tabulek. Zde je vizualizace:

Syntaxe operátoru INTERSECT je následující:

SELECT COLUMN1, 
       COLUMN2, 
       COLUMN3, 
       COLUMN4..FROM TABLE1 
INTERSECT
SELECT COLUMN1, 
       COLUMN2, 
       COLUMN3, 
       COLUMN4..FROM TABLE2

Co je operátor EXCEPT

EXCEPT se používá k načtení záznamů, které byly nalezeny v jednom dotazu, ale ne v jiném dotazu. Jinými slovy, vrací záznamy, které jsou jedinečné pro jednu sadu výsledků. Takto to vypadá ve vizualizaci:

Syntaxe operátoru EXCEPT je následující:

SELECT COLUMN1, 
       COLUMN2, 
       COLUMN3, 
       COLUMN4..FROM TABLE1 
EXCEPT
SELECT COLUMN1, 
       COLUMN2, 
       COLUMN3, 
       COLUMN4..FROM TABLE2

Pojďme vytvořit ukázkové nastavení, abychom ukázali, jak lze tyto operátory používat.

Nastavení ukázky

Abych předvedl INTERSECT a EXCEPT, vytvořil jsem dvě tabulky s názvem Zaměstnanec a Stážista .

Provedením následujícího dotazu vytvořte tyto tabulky:

CREATE TABLE [DBO].[EMPLOYEE] 
  ( 
     [NAME]             [NVARCHAR](250) NOT NULL, 
     [BUSINESSENTITYID] [INT] NOT NULL, 
     [NATIONALIDNUMBER] [NVARCHAR](15) NOT NULL, 
     [LOGINID]          [NVARCHAR](256) NOT NULL, 
     [BIRTHDATE]        [DATE] NOT NULL, 
     [MARITALSTATUS]    [NCHAR](1) NOT NULL, 
     [GENDER]           [NCHAR](1) NOT NULL 
  ) 
ON [PRIMARY] 

CREATE TABLE [DBO].[TRAINEE] 
  ( 
     [NAME]             [NVARCHAR](250) NOT NULL, 
     [BUSINESSENTITYID] [INT] NOT NULL, 
     [NATIONALIDNUMBER] [NVARCHAR](15) NOT NULL, 
     [BIRTHDATE]        [DATE] NOT NULL, 
     [GENDER]           [NCHAR](1) NOT NULL 
  ) 
ON [PRIMARY]

Nyní do položky Zaměstnanec vložíme nějaká fiktivní data tabulky provedením následujícího dotazu:

INSERT [DBO].[EMPLOYEE] ([NAME], [BUSINESSENTITYID], [NATIONALIDNUMBER], [LOGINID], [BIRTHDATE], [MARITALSTATUS], [GENDER]) VALUES (N'KEN SÁNCHEZ', 1, N'295847284', N'ADVENTURE-WORKS\KEN0', CAST(N'1969-01-29' AS DATE), N'S', N'M')
GO
INSERT [DBO].[EMPLOYEE] ([NAME], [BUSINESSENTITYID], [NATIONALIDNUMBER], [LOGINID], [BIRTHDATE], [MARITALSTATUS], [GENDER]) VALUES (N'TERRI DUFFY', 2, N'245797967', N'ADVENTURE-WORKS\TERRI0', CAST(N'1971-08-01' AS DATE), N'S', N'F')
GO
INSERT [DBO].[EMPLOYEE] ([NAME], [BUSINESSENTITYID], [NATIONALIDNUMBER], [LOGINID], [BIRTHDATE], [MARITALSTATUS], [GENDER]) VALUES (N'ROBERTO TAMBURELLO', 3, N'509647174', N'ADVENTURE-WORKS\ROBERTO0', CAST(N'1974-11-12' AS DATE), N'M', N'M')
GO
INSERT [DBO].[EMPLOYEE] ([NAME], [BUSINESSENTITYID], [NATIONALIDNUMBER], [LOGINID], [BIRTHDATE], [MARITALSTATUS], [GENDER]) VALUES (N'ROB WALTERS', 4, N'112457891', N'ADVENTURE-WORKS\ROB0', CAST(N'1974-12-23' AS DATE), N'S', N'M')
GO
INSERT [DBO].[EMPLOYEE] ([NAME], [BUSINESSENTITYID], [NATIONALIDNUMBER], [LOGINID], [BIRTHDATE], [MARITALSTATUS], [GENDER]) VALUES (N'GAIL ERICKSON', 5, N'695256908', N'ADVENTURE-WORKS\GAIL0', CAST(N'1952-09-27' AS DATE), N'M', N'F')
GO
INSERT [DBO].[EMPLOYEE] ([NAME], [BUSINESSENTITYID], [NATIONALIDNUMBER], [LOGINID], [BIRTHDATE], [MARITALSTATUS], [GENDER]) VALUES (N'JOSSEF GOLDBERG', 6, N'998320692', N'ADVENTURE-WORKS\JOSSEF0', CAST(N'1959-03-11' AS DATE), N'M', N'M')

Dále uděláme totéž pro Účastníka tabulka:

INSERT [DBO].[TRAINEE] ([NAME], [BUSINESSENTITYID], [NATIONALIDNUMBER], [BIRTHDATE], [GENDER]) VALUES (N'JOHN WOOD', 18, N'222969461', CAST(N'1978-03-06' AS DATE), N'M')
GO
INSERT [DBO].[TRAINEE] ([NAME], [BUSINESSENTITYID], [NATIONALIDNUMBER], [BIRTHDATE], [GENDER]) VALUES (N'MARY DEMPSEY', 19, N'52541318', CAST(N'1978-01-29' AS DATE), N'F')
GO
INSERT [DBO].[TRAINEE] ([NAME], [BUSINESSENTITYID], [NATIONALIDNUMBER], [BIRTHDATE], [GENDER]) VALUES (N'WANIDA BENSHOOF', 20, N'323403273', CAST(N'1975-03-17' AS DATE), N'F')
GO
INSERT [DBO].[TRAINEE] ([NAME], [BUSINESSENTITYID], [NATIONALIDNUMBER], [BIRTHDATE], [GENDER]) VALUES (N'KEN SÁNCHEZ', 1, N'295847284', CAST(N'1969-01-29' AS DATE), N'M')
GO
INSERT [DBO].[TRAINEE] ([NAME], [BUSINESSENTITYID], [NATIONALIDNUMBER], [BIRTHDATE], [GENDER]) VALUES (N'TERRI DUFFY', 2, N'245797967', CAST(N'1971-08-01' AS DATE),  N'F')
GO
INSERT [DBO].[TRAINEE] ([NAME], [BUSINESSENTITYID], [NATIONALIDNUMBER], [BIRTHDATE], [GENDER]) VALUES (N'ROBERTO TAMBURELLO', 3, N'509647174', CAST(N'1974-11-12' AS DATE), N'M')
GO

Nyní pomocí INTERSECT načteme seznam zaměstnanců, kteří jsou společné pro obě tabulky. Chcete-li to provést, spusťte následující dotaz:

SELECT NAME, 
       BUSINESSENTITYID, 
       NATIONALIDNUMBER, 
       BIRTHDATE, 
       GENDER 
FROM   EMPLOYEE 
INTERSECT 
SELECT NAME, 
       BUSINESSENTITYID, 
       NATIONALIDNUMBER, 
       BIRTHDATE, 
       GENDER 
FROM   TRAINEE

Výstup tohoto dotazu by měl být následující:

Jak můžete vidět na obrázku výše, dotaz vrátil pouze záznamy, které jsou společné pro obě tabulky.

INNER JOIN vs. INTERSECT

Ve většině případů INTERSECT a INNER JOIN vrátí stejný výstup, ale existují výjimky. To nám pomůže pochopit jednoduchý příklad.

Pojďme přidat nějaké duplicitní záznamy do tabulky Trainee. Proveďte následující dotaz:

INSERT [DBO].[TRAINEE] ([NAME], [BUSINESSENTITYID], [NATIONALIDNUMBER], [BIRTHDATE], [GENDER]) VALUES (N'TERRI DUFFY', 2, N'245797967', CAST(N'1971-08-01' AS DATE),  N'F')
GO
INSERT [DBO].[TRAINEE] ([NAME], [BUSINESSENTITYID], [NATIONALIDNUMBER], [BIRTHDATE], [GENDER]) VALUES (N'ROBERTO TAMBURELLO', 3, N'509647174', CAST(N'1974-11-12' AS DATE), N'M')
GO

Nyní se pokusíme vygenerovat požadovaný výstup pomocí INTERSECT.

SELECT NAME,BUSINESSENTITYID,NATIONALIDNUMBER,BIRTHDATE,GENDER FROM EMPLOYEE
INTERSECT
SELECT NAME,BUSINESSENTITYID,NATIONALIDNUMBER,BIRTHDATE,GENDER FROM TRAINEE

Toto je výstup, který dostáváme:

Nyní zkusme použít INNER JOIN.

SELECT A.NAME, 
       A.BUSINESSENTITYID, 
       A.NATIONALIDNUMBER, 
       A.BIRTHDATE, 
       A.GENDER 
FROM   EMPLOYEE A 
       INNER JOIN TRAINEE B 
               ON A.NAME = B.NAME

Výstup, který v tomto případě získáme, je následující:

Nyní, jak můžete vidět na obrázku výše, INNER JOIN načte záznamy, které jsou společné pro obě tabulky. Vyplní všechny záznamy z pravé tabulky. Proto můžete vidět duplicitní záznamy.

Nyní přidejte klíčové slovo DISTINCT do dotazu INNER JOIN a podívejme se, co to udělá:

SELECT DISTINCT A.NAME, 
                A.BUSINESSENTITYID, 
                A.NATIONALIDNUMBER, 
                A.BIRTHDATE, 
                A.GENDER 
FROM   EMPLOYEE A 
       INNER JOIN TRAINEE B 
               ON A.NAME = B.NAME

Výstup by měl vypadat takto:

Jak můžete vidět na snímku obrazovky výše, duplicitní záznamy byly odstraněny.

INTERSECT a INNER JOIN zacházejí s hodnotami NULL odlišně. U INNER JOIN jsou dvě hodnoty NULL různé, takže existuje šance, že je přeskočí při spojování dvou stolů.

Na druhou stranu INTERSECT považuje dvě hodnoty NULL za stejné, takže záznamy, které mají hodnoty NULL, nebudou odstraněny. Abyste tomu lépe porozuměli, podívejme se na příklad.

Nejprve do Tréninku přidejte některé hodnoty NULL a Zaměstnanec tabulky provedením následujícího dotazu:

INSERT [DBO].[TRAINEE] ([NAME], [BUSINESSENTITYID], [NATIONALIDNUMBER], [BIRTHDATE], [GENDER]) VALUES (NULL, 3, N'509647174', CAST(N'1974-11-12' AS DATE), N'M')
GO

INSERT [DBO].[Employee] ([NAME], [BUSINESSENTITYID], [NATIONALIDNUMBER],[LOGINID], [BIRTHDATE],[MARITALSTATUS], [GENDER]) VALUES (NULL, 3, N'509647174','ADVENTURE-WORKS\TERRI0', CAST(N'1974-11-12' AS DATE),  N'M',N'M')
GO

Nyní se pokusíme získat záznamy společné pro tyto dvě tabulky pomocí INTERSECT a INNER JOIN. Budete muset provést následující dotaz:

/*QUERY WITH INTERSECT*/ 
SELECT NAME, 
       BUSINESSENTITYID, 
       NATIONALIDNUMBER, 
       BIRTHDATE, 
       GENDER 
FROM   EMPLOYEE 
INTERSECT 
SELECT NAME, 
       BUSINESSENTITYID, 
       NATIONALIDNUMBER, 
       BIRTHDATE, 
       GENDER 
FROM   TRAINEE 

/*QUERY WITH INNER JOIN*/ 
SELECT A.NAME, 
       A.BUSINESSENTITYID, 
       A.NATIONALIDNUMBER, 
       A.BIRTHDATE, 
       A.GENDER 
FROM   EMPLOYEE A 
       INNER JOIN TRAINEE B 
               ON A.NAME = B.NAME

Toto je výstup, který bychom jako výsledek měli dostat:

Jak můžete vidět výše, sada výsledků generovaná pomocí INTERSECT obsahuje hodnoty NULL, zatímco INNER JOIN přeskočil záznamy, které mají hodnoty NULL.

KROMĚ operátora

Abychom předvedli operátor EXCEPT v akci, podívejme se na případ použití. Chci například vyplnit podrobnosti o zaměstnankyních z tabulky Zaměstnanec. K tomu nám pomůže následující dotaz:

SELECT NAME, 
       BUSINESSENTITYID, 
       NATIONALIDNUMBER, 
       BIRTHDATE, 
       GENDER 
FROM   EMPLOYEE 
WHERE  GENDER = 'F' 
EXCEPT 
SELECT NAME, 
       BUSINESSENTITYID, 
       NATIONALIDNUMBER, 
       BIRTHDATE, 
       GENDER 
FROM   EMPLOYEE 
WHERE  GENDER = 'M'

Toto je výstup, který dostáváme:

Jak můžete vidět výše, dotaz vyplnil pouze údaje o zaměstnankyních.

Sadu výsledků můžete také naplnit pomocí dílčího dotazu:

SELECT NAME, 
       BUSINESSENTITYID, 
       NATIONALIDNUMBER, 
       BIRTHDATE, 
       GENDER 
FROM   EMPLOYEE AS M 
WHERE  GENDER = 'F' 
       AND GENDER NOT IN (SELECT GENDER 
                          FROM   EMPLOYEE AS F 
                          WHERE  GENDER = 'M')

Omezení INTERSECT a EXCEPT

  1. Nemůžeme použít EXCEPT a INTERSECT v definicích distribuovaného rozděleného pohledu s klauzulemi COMPUTE a COMPUTE BY.
  2. EXCEPT a INTERSECT lze použít v rychlých kurzorech pouze vpřed a ve statických kurzorech.
  3. EXCEPT a INTERSECT lze použít v distribuovaných dotazech, ale lze je spustit pouze na místním serveru. Nemůžete je spustit na vzdáleném serveru.

Shrnutí

V tomto článku jsem se zabýval:

  1. Operátory EXCEPT a INTERSECT.
  2. Rozdíl mezi INTERSECT a INNER JOIN.
  3. Podrobné vysvětlení operátorů INTERSECT a EXCEPT s příkladem.

  1. Ladění výkonu dotazů MySQL

  2. Změňte funkci s hodnotou tabulky na serveru SQL Server

  3. SQLite FULL OUTER JOIN emulace

  4. Průvodce automatizovaným nasazením cloudové databáze