Database
 sql >> Baza danych >  >> RDS >> Database

Operatory zbioru T-SQL Część 2:PRZECIĘCIE i Z WYJĄTKIEM

W moim poprzednim artykule wyjaśniłem podstawy operatorów mnogościowych, ich typy i warunki ich użycia. Mówiłem również o operatorach UNION i UNION ALL, ich zastosowaniu i różnicach.

W tym artykule dowiemy się, co następuje:

  1. Operatory EXCEPT i INTERSECT.
  2. Różnica między INTERSECT i INNER JOIN.
  3. Szczegółowe objaśnienie INTERSECT i Z WYJĄTKIEM przykładu.

Operatory EXCEPT i INTERSECT zostały wprowadzone w SQL Server 2005. Oba są operatorami zestawów używanymi do łączenia zestawów wyników wygenerowanych przez dwa zapytania i pobierania żądanego wyniku.

Co to jest operator INTERSECT

INTERSECT służy do pobierania rekordów wspólnych dla wszystkich zestawów danych pobranych z wielu zapytań lub tabel. Oto wizualizacja tego:

Składnia operatora INTERSECT jest następująca:

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

Co to jest operator Z WYJĄTKIEM

Z WYJĄTKIEM służy do pobierania rekordów znalezionych w jednym zapytaniu, ale nie w innym zapytaniu. Innymi słowy, zwraca rekordy, które są unikalne dla jednego zestawu wyników. Tak to wygląda na wizualizacji:

Składnia operatora EXCEPT jest następująca:

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

Stwórzmy konfigurację demonstracyjną, aby zademonstrować, jak można używać tych operatorów.

Konfiguracja wersji demonstracyjnej

Aby zademonstrować INTERSECT i EXCEPT, utworzyłem dwie tabele o nazwie Pracownik i Praktykant .

Wykonaj następujące zapytanie, aby utworzyć te tabele:

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]

Teraz wstawmy kilka fikcyjnych danych do Pracownika tabeli, wykonując następujące zapytanie:

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

Następnie zrobimy to samo dla stażysty tabela:

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

Teraz użyjmy INTERSECT, aby pobrać listę pracowników wspólnych dla obu tabel. Aby to zrobić, uruchom następujące zapytanie:

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

Wynik tego zapytania powinien wyglądać następująco:

Jak widać na powyższym zrzucie ekranu, zapytanie zwróciło tylko rekordy, które są wspólne dla obu tabel.

ZŁĄCZENIE WEWNĘTRZNE a PRZECIĘCIE

W większości przypadków INTERSECT i INNER JOIN zwracają te same dane wyjściowe, ale są pewne wyjątki. Prosty przykład pomoże nam to zrozumieć.

Dodajmy kilka zduplikowanych rekordów do tabeli Trainee. Wykonaj następujące zapytanie:

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

Teraz spróbujemy wygenerować żądany wynik za pomocą INTERSECT.

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

Oto wynik, który otrzymujemy:

Teraz spróbujmy użyć 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

Wynik jaki otrzymujemy w tym przypadku jest następujący:

Teraz, jak widać na powyższym zrzucie ekranu, INNER JOIN pobiera rekordy, które są wspólne dla obu tabel. Wypełnia wszystkie rekordy z prawej tabeli. Dlatego możesz zobaczyć zduplikowane rekordy.

Teraz dodajmy słowo kluczowe DISTINCT do zapytania INNER JOIN i zobaczmy, co to daje:

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

Wynik powinien wyglądać tak:

Jak widać na powyższym zrzucie ekranu, zduplikowane rekordy zostały wyeliminowane.

INTERSECT i INNER JOIN traktują wartości NULL inaczej. W przypadku INNER JOIN dwie wartości NULL są różne, więc istnieje prawdopodobieństwo, że pominie je podczas dołączania do dwóch stołów.

Z drugiej strony, INTERSECT traktuje dwie wartości NULL jako takie same, więc rekordy, które mają wartości NULL, nie zostaną wyeliminowane. Aby lepiej to zrozumieć, spójrzmy na przykład.

Najpierw dodajmy kilka wartości NULL do Stażysty i Pracownik tabele, wykonując następujące zapytanie:

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

Teraz spróbujmy pobrać rekordy wspólne dla dwóch tabel za pomocą INTERSECT i INNER JOIN. Musisz wykonać następujące zapytanie:

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

Oto wynik, który powinniśmy otrzymać w rezultacie:

Jak widać powyżej, zestaw wyników wygenerowany przez INTERSECT zawiera wartości NULL, podczas gdy INNER JOIN pominął rekordy, które mają wartości NULL.

Z WYJĄTKIEM operatora

Aby zademonstrować działanie operatora EXCEPT, spójrzmy na przypadek użycia. Na przykład chcę wypełnić dane pracownic z tabeli Pracownik. Pomoże nam w tym następujące zapytanie:

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

Oto wynik, który otrzymujemy:

Jak widać powyżej, zapytanie zawierało tylko dane pracownic.

Możesz również wypełnić zestaw wyników za pomocą podzapytania:

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

Ograniczenia INTERSECT i Z WYJĄTKIEM

  1. Nie możemy używać EXCEPT i INTERSECT w definicjach rozproszonych widoków partycjonowanych z klauzulami COMPUTE i COMPUTE BY.
  2. EXCEPT i INTERSECT mogą być używane w kursorach tylko do szybkiego przewijania do przodu i statycznych.
  3. EXCEPT i INTERSECT mogą być używane w zapytaniach rozproszonych, ale mogą być wykonywane tylko na serwerze lokalnym. Nie możesz ich uruchomić na zdalnym serwerze.

Podsumowanie

W tym artykule omówiłem:

  1. Operatory EXCEPT i INTERSECT.
  2. Różnica między INTERSECT i INNER JOIN.
  3. Szczegółowe wyjaśnienie operatorów INTERSECT i EXCEPT z przykładem.

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Historia poleceń w isql

  2. Zrozumienie czasów operatora planu wykonania

  3. Jak działa model usług PAAS?

  4. Poprawa utrzymania partycji dzięki przyrostowym statystykom

  5. SQL, dodawanie danych do tabeli