sql >> Database teknologi >  >> RDS >> Database

T-SQL SET-operatører, del 2:STYR OG UNDTAG

I min tidligere artikel forklarede jeg det grundlæggende om sætoperatører, deres typer og forudsætninger for deres brug. Jeg talte også om UNION og UNION ALL operatører, deres brug og forskelle.

I denne artikel skal vi lære følgende:

  1. EXCEPT og INTERSECT-operatorer.
  2. Forskel mellem INTERSECT og INNER JOIN.
  3. Den detaljerede forklaring af INTERSECT og EXCEPT med et eksempel.

EXCEPT- og INTERSECT-operatorer blev introduceret i SQL Server 2005. Begge er sæt-operatorer, der bruges til at kombinere resultatsæt genereret af to forespørgsler og hente det ønskede output.

Hvad er INTERSECT-operatøren

INTERSECT bruges til at få poster, der er fælles for alle datasæt, hentet fra flere forespørgsler eller tabeller. Her er en visualisering af dette:

Syntaksen for INTERSECT-operatoren er som følger:

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

Hvad er EXCEPT-operatøren

EXCEPT bruges til at hente poster, som findes i én forespørgsel, men ikke i en anden forespørgsel. Med andre ord returnerer den poster, som er unikke for ét resultatsæt. Sådan ser det ud visualiseret:

Syntaksen for operatoren EXCEPT er som følger:

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

Lad os lave en demo-opsætning for at demonstrere, hvordan disse operatører kan bruges.

Demoopsætning

For at demonstrere INTERSECT og EXCEPT oprettede jeg to tabeller med navnet Medarbejder og elev .

Kør følgende forespørgsel for at oprette disse 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]

Lad os nu indsætte nogle dummy-data i medarbejderen tabel ved at udføre følgende forespørgsel:

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')

Dernæst vil vi gøre det samme for praktikanten tabel:

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

Lad os nu bruge INTERSECT til at hente listen over medarbejdere, der er fælles for begge tabeller. For at gøre det skal du køre følgende forespørgsel:

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

Outputtet af denne forespørgsel skal være som følger:

Som du kan se på skærmbilledet ovenfor, har forespørgslen kun returneret poster, som er fælles for begge tabeller.

INNER JOIN vs. INTERSECT

I de fleste tilfælde returnerer INTERSECT og INNER JOIN det samme output, men der er nogle undtagelser. Et simpelt eksempel vil hjælpe os med at forstå dette.

Lad os tilføje nogle duplikerede poster til Trainee-tabellen. Udfør følgende forespørgsel:

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 vil vi forsøge at generere det ønskede output ved hjælp af INTERSECT.

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

Dette er det output, vi får:

Lad os nu prøve at bruge 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

Det output, vi får i dette tilfælde, er som følger:

Nu, som du kan se på skærmbilledet ovenfor, henter INNER JOIN poster, som er fælles for begge tabeller. Den udfylder alle poster fra den højre tabel. Derfor kan du se duplikerede poster.

Lad os nu tilføje DISTINCT søgeordet til INNER JOIN-forespørgslen og se på, hvad dette 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

Outputtet skal se sådan ud:

Som du kan se på skærmbilledet ovenfor, er duplikerede poster blevet elimineret.

INTERSECT og INNER JOIN behandler NULL-værdier forskelligt. For INNER JOIN er to NULL-værdier forskellige, så der er chancer for, at den springer dem over, mens de forbinder to tabeller.

På den anden side behandler INTERSECT to NULL-værdier som værende ens, så poster, der har NULL-værdier, vil ikke blive elimineret. For at forstå det bedre, lad os se på et eksempel.

Lad os først tilføje nogle NULL-værdier til Trainee og medarbejder tabeller ved at udføre følgende forespørgsel:

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

Lad os nu prøve at hente poster, der er fælles for de to tabeller, ved hjælp af INTERSECT og INNER JOIN. Du skal udføre følgende forespørgsel:

/*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

Dette er det output, vi bør få som et resultat:

Som du kan se ovenfor, indeholder resultatsættet genereret af INTERSECT NULL-værdier, mens INNER JOIN sprang de poster over, der har NULL-værdier.

UNDTAGET operatøren

For at demonstrere EXCEPT-operatøren i aktion, lad os se på en use case. For eksempel vil jeg udfylde oplysningerne om kvindelige medarbejdere fra tabellen medarbejder. Følgende forespørgsel hjælper os med at gøre netop det:

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

Dette er det output, vi får:

Som du kan se ovenfor, udfyldte forespørgslen kun de kvindelige medarbejderes oplysninger.

Du kan også udfylde resultatsættet ved hjælp af en underforespørgsel:

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ænsninger for INTERSECT og EXCEPT

  1. Vi kan ikke bruge EXCEPT og INTERSECT i distribuerede partitionerede visningsdefinitioner med COMPUTE- og COMPUTE BY-sætninger.
  2. EXCEPT og INTERSECT kan bruges i fast forward-kun og statiske markører.
  3. EXCEPT og INTERSECT kan bruges i distribuerede forespørgsler, men kan kun udføres på den lokale server. Du kan ikke køre dem på en ekstern server.

Oversigt

I denne artikel har jeg dækket:

  1. EXCEPT- og INTERSECT-operatørerne.
  2. Forskellen mellem INTERSECT og INNER JOIN.
  3. En detaljeret forklaring af operatorerne INTERSECT og EXCEPT med et eksempel.

  1. COMPOSE() Funktion i Oracle

  2. Forbindelsestimeout for SQL-server

  3. SQL Server 2016 Temporal Table Query Plan Behavior

  4. SQL Server:det maksimale antal rækker i tabellen