I min tidigare artikel förklarade jag grunderna för setoperatorer, deras typer och förutsättningar för deras användning. Jag pratade också om UNION och UNION ALL operatörer, deras användning och skillnader.
I den här artikeln kommer vi att lära oss följande:
- UTOM och INTERSECT-operatorer.
- Skillnaden mellan INTERSECT och INNER JOIN.
- Den detaljerade förklaringen av INTERSECT och EXCEPT med ett exempel.
EXCEPT- och INTERSECT-operatorerna introducerades i SQL Server 2005. Båda är setoperatorer som används för att kombinera resultatuppsättningarna som genereras av två frågor och hämta önskad utdata.
Vad är INTERSECT-operatören
INTERSECT används för att få poster som är gemensamma för alla datamängder som hämtas från flera frågor eller tabeller. Här är en visualisering av detta:
Syntaxen för INTERSECT-operatorn är följande:
SELECT COLUMN1, COLUMN2, COLUMN3, COLUMN4..FROM TABLE1 INTERSECT SELECT COLUMN1, COLUMN2, COLUMN3, COLUMN4..FROM TABLE2
Vad är operatorn EXCEPT
EXCEPT används för att hämta poster som finns i en fråga men inte i en annan fråga. Med andra ord returnerar den poster som är unika för en resultatuppsättning. Så här ser det ut visualiserat:
Syntaxen för operatorn EXCEPT är följande:
SELECT COLUMN1, COLUMN2, COLUMN3, COLUMN4..FROM TABLE1 EXCEPT SELECT COLUMN1, COLUMN2, COLUMN3, COLUMN4..FROM TABLE2
Låt oss skapa en demo-inställning för att visa hur dessa operatörer kan användas.
Demoinställningar
För att demonstrera INTERSECT och EXCEPT skapade jag två tabeller med namnet Anställd och Trainee .
Kör följande fråga för att skapa dessa tabeller:
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]
Nu ska vi infoga lite dummydata i anställd tabell genom att köra följande fråga:
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ärefter gör vi samma sak för praktikanten tabell:
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
Låt oss nu använda INTERSECT för att hämta listan över anställda som är gemensamma för båda tabellerna. För att göra det, kör följande fråga:
SELECT NAME, BUSINESSENTITYID, NATIONALIDNUMBER, BIRTHDATE, GENDER FROM EMPLOYEE INTERSECT SELECT NAME, BUSINESSENTITYID, NATIONALIDNUMBER, BIRTHDATE, GENDER FROM TRAINEE
Utdata från denna fråga bör vara följande:
Som du kan se i skärmdumpen ovan har frågan endast returnerat poster som är gemensamma för båda tabellerna.
INNER JOIN vs. INTERSECT
I de flesta fall returnerar INTERSECT och INNER JOIN samma utdata, men det finns några undantag. Ett enkelt exempel hjälper oss att förstå detta.
Låt oss lägga till några dubbletter av poster i Trainee-tabellen. Kör följande fråga:
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
Nu ska vi försöka generera önskad utdata med INTERSECT.
SELECT NAME,BUSINESSENTITYID,NATIONALIDNUMBER,BIRTHDATE,GENDER FROM EMPLOYEE INTERSECT SELECT NAME,BUSINESSENTITYID,NATIONALIDNUMBER,BIRTHDATE,GENDER FROM TRAINEE
Det här är resultatet vi får:
Nu ska vi försöka använda 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
Resultatet vi får i det här fallet är följande:
Nu, som du kan se på skärmdumpen ovan, hämtar INNER JOIN poster som är gemensamma för båda tabellerna. Den fyller i alla poster från den högra tabellen. Därför kan du se dubbletter av poster.
Låt oss nu lägga till nyckelordet DISTINCT i INNER JOIN-frågan och titta på vad detta gör:
SELECT DISTINCT A.NAME, A.BUSINESSENTITYID, A.NATIONALIDNUMBER, A.BIRTHDATE, A.GENDER FROM EMPLOYEE A INNER JOIN TRAINEE B ON A.NAME = B.NAME
Utdata ska se ut så här:
Som du kan se på skärmdumpen ovan har dubblettposter eliminerats.
INTERSECT och INNER JOIN behandlar NULL-värden olika. För INNER JOIN är två NULL-värden olika, så det finns chanser att det hoppar över dem när två tabeller slås samman.
Å andra sidan behandlar INTERSECT två NULL-värden som samma, så poster som har NULL-värden kommer inte att elimineras. För att förstå det bättre, låt oss titta på ett exempel.
Låt oss först lägga till några NULL-värden till Trainee och Anställd tabeller genom att köra följande fråga:
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
Låt oss nu försöka hämta poster som är gemensamma för de två tabellerna med hjälp av INTERSECT och INNER JOIN. Du måste utföra följande fråga:
/*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
Detta är resultatet vi bör få som ett resultat:
Som du kan se ovan innehåller resultatuppsättningen som genereras av INTERSECT NULL-värden, medan INNER JOIN hoppade över posterna som har NULL-värden.
UTOM operatören
För att demonstrera EXCEPT-operatören i aktion, låt oss titta på ett användningsfall. Till exempel vill jag fylla i uppgifterna om kvinnliga anställda från tabellen Anställda. Följande fråga hjälper oss att göra just det:
SELECT NAME, BUSINESSENTITYID, NATIONALIDNUMBER, BIRTHDATE, GENDER FROM EMPLOYEE WHERE GENDER = 'F' EXCEPT SELECT NAME, BUSINESSENTITYID, NATIONALIDNUMBER, BIRTHDATE, GENDER FROM EMPLOYEE WHERE GENDER = 'M'
Det här är resultatet vi får:
Som du kan se ovan fyllde frågan endast i de kvinnliga anställdas uppgifter.
Du kan också fylla i resultatuppsättningen med hjälp av en underfråga:
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')
Begränsningar för INTERSECT och EXCEPT
- Vi kan inte använda EXCEPT och INTERSECT i distribuerade partitionerade vydefinitioner med COMPUTE- och COMPUTE BY-satser.
- EXCEPT och INTERSECT kan användas i enbart snabbspolning framåt och statiska markörer.
- EXCEPT och INTERSECT kan användas i distribuerade frågor, men kan bara köras på den lokala servern. Du kan inte köra dem på en fjärrserver.
Sammanfattning
I den här artikeln har jag täckt:
- operatorerna EXCEPT och INTERSECT.
- Skillnaden mellan INTERSECT och INNER JOIN.
- En detaljerad förklaring av operatorerna INTERSECT och EXCEPT med ett exempel.