Database
 sql >> база данни >  >> RDS >> Database

Оператори на T-SQL SET Част 2:INTERSECT и EXCEPT

В предишната си статия обясних основите на операторите за множество, техните типове и предпоставките за тяхното използване. Говорих също за операторите UNION и UNION ALL, тяхното използване и разлики.

В тази статия ще научим следното:

  1. Оператори EXCEPT и INTERSECT.
  2. Разлика между INTERSECT и INNER JOIN.
  3. Подробното обяснение на INTERSECT и EXCEPT с пример.

Операторите EXCEPT и INTERSECT бяха въведени в SQL Server 2005. И двата са оператори за набор, използвани за комбиниране на резултантните набори, генерирани от две заявки, и извличане на желания резултат.

Какво е операторът INTERSECT

INTERSECT се използва за получаване на записи, общи за всички набори от данни, извлечени от множество заявки или таблици. Ето визуализация на това:

Синтаксисът на оператора INTERSECT е следният:

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

Какво е операторът EXCEPT

EXCEPT се използва за извличане на записи, които са открити в една заявка, но не и в друга заявка. С други думи, той връща записи, които са уникални за един набор от резултати. Ето как изглежда визуализирано:

Синтаксисът на оператора EXCEPT е както следва:

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

Нека създадем демонстрационна настройка, за да демонстрираме как могат да се използват тези оператори.

Настройка на демонстрация

За да демонстрирам INTERSECT и EXCEPT, създадох две таблици с име Служител истажант .

Изпълнете следната заявка, за да създадете тези таблици:

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]

Сега нека вмъкнем някои фиктивни данни в Служител таблица, като изпълните следната заявка:

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

След това ще направим същото за стажанта таблица:

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

Сега нека използваме INTERSECT, за да извлечем списъка със служители, които са общи за двете таблици. За да направите това, изпълнете следната заявка:

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

Резултатът от тази заявка трябва да бъде както следва:

Както можете да видите на екранната снимка по-горе, заявката е върнала само записи, които са общи и за двете таблици.

INNER JOIN срещу INTERSECT

В повечето случаи INTERSECT и INNER JOIN връщат същия изход, но има някои изключения. Един прост пример ще ни помогне да разберем това.

Нека добавим няколко дублирани записи към таблицата на стажантите. Изпълнете следната заявка:

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

Сега ще се опитаме да генерираме желания изход с помощта на INTERSECT.

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

Това е изходът, който получаваме:

Сега нека опитаме да използваме 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

Резултатът, който получаваме в този случай, е както следва:

Сега, както можете да видите на екранната снимка по-горе, INNER JOIN извлича записи, които са общи и за двете таблици. Той попълва всички записи от дясната таблица. Следователно можете да видите дублиращи се записи.

Сега нека добавим ключовата дума DISTINCT към заявката INNER JOIN и да видим какво прави това:

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

Резултатът трябва да изглежда така:

Както можете да видите на екранната снимка по-горе, дублиращите се записи са елиминирани.

INTERSECT и INNER JOIN третират NULL стойностите по различен начин. За INNER JOIN две стойности NULL са различни, така че има шансове да ги пропусне, докато съединява две таблици.

От друга страна, INTERSECT третира две стойности NULL като еднакви, така че записи, които имат стойности NULL, няма да бъдат елиминирани. За да го разберем по-добре, нека разгледаме пример.

Първо, нека добавим някои NULL стойности към Стажант и Служител таблици, като изпълните следната заявка:

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

Сега нека се опитаме да извлечем записи, общи за двете таблици, използвайки INTERSECT и INNER JOIN. Ще трябва да изпълните следната заявка:

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

Това е изходът, който трябва да получим като резултат:

Както можете да видите по-горе, резултатният набор, генериран от INTERSECT, съдържа NULL стойности, докато INNER JOIN пропусна записите, които имат стойности NULL.

Оператор ОСВЕН

За да демонстрираме оператора EXCEPT в действие, нека разгледаме случай на употреба. Например, искам да попълня данните за служителите от таблицата на служителите. Следната заявка ще ни помогне да направим точно това:

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

Това е изходът, който получаваме:

Както можете да видите по-горе, заявката попълни само данни за служителите.

Можете също да попълните набора от резултати с помощта на подзаявка:

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

Ограничения на INTERSECT и EXCEPT

  1. Не можем да използваме EXCEPT и INTERSECT в дефинициите на разпределен разделен изглед с клаузи COMPUTE и COMPUTE BY.
  2. EXCEPT и INTERSECT могат да се използват в курсори само за бързо превъртане напред и статични курсори.
  3. EXCEPT и INTERSECT могат да се използват в разпределени заявки, но могат да се изпълняват само на локалния сървър. Не можете да ги стартирате на отдалечен сървър.

Резюме

В тази статия разгледах:

  1. Операторите EXCEPT и INTERSECT.
  2. Разликата между INTERSECT и INNER JOIN.
  3. Подробно обяснение на операторите INTERSECT и EXCEPT с пример.

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. VLDBs при 20-тийнейджърите:Ще ви трябва по-голям...

  2. NoSQL:живот без схема

  3. Преминете към стартиране на разработване на база данни, управлявано от тестове (TDDD)

  4. Git Съвети и най-добри практики за начинаещи

  5. Топ блогове за база данни, които да следвате