sql >> Databasteknik >  >> RDS >> Database

T-SQL SET Operatörer del 2:KORS och UTOM

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:

  1. UTOM och INTERSECT-operatorer.
  2. Skillnaden mellan INTERSECT och INNER JOIN.
  3. 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

  1. Vi kan inte använda EXCEPT och INTERSECT i distribuerade partitionerade vydefinitioner med COMPUTE- och COMPUTE BY-satser.
  2. EXCEPT och INTERSECT kan användas i enbart snabbspolning framåt och statiska markörer.
  3. 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:

  1. operatorerna EXCEPT och INTERSECT.
  2. Skillnaden mellan INTERSECT och INNER JOIN.
  3. En detaljerad förklaring av operatorerna INTERSECT och EXCEPT med ett exempel.

  1. Hur beräknar jag en löpande summa i SQL utan att använda en markör?

  2. Så här konfigurerar du kluster-till-klusterreplikering för PostgreSQL

  3. viloläge orakelsekvens producerar stort gap

  4. DAYOFMONTH() Exempel – MySQL