Pytanie odnośnie podzapytań (MS SQL Server)

0

Witam,
Przerabiam sobie kursik z neta o Bazach Danych. Wykorzystuje do tego MS SQL Server 2008 i bazę AdventureWorks2008RC

Pytanie dotyczy podzapytań.

Mamy dwie tabele:

[Person].[Person]
z kolumnami: BusinessEntityID, FirstName, LastName, ....

[HumanResources].[Employee]
z kolumnami: BusinessEntityID, LoginID, JobTitle, ....

Poniższe podzapytanie rozumiem, tylko wcześniej przerabiałem konstrukcje z JOIN .. ON , którą można tutaj zastosować zamiennie. Owa konstrukcja była na tyle dobra, że można było wypisać jeszcze JobTitle wraz z Imieniem i Nazwiskiem.
Tutaj w podzapytaniu nie mogę tego zastosować. Idzie w ogóle to wykonać?

SELECT FirstName, LastName
FROM   Person.Person
WHERE  BusinessEntityID IN
                  (SELECT BusinessEntityID
                  FROM    HumanResources.Employee
                  WHERE   (JobTitle LIKE '%Vice President%'))

Mam nadzieje, że coś z tego zrozumiecie ;)

0

Nie wiem, czy dobrze zrozumiełem - chcesz znaleźć wszystkich Janów Kowalskich, którzy są Vice President? No to zrób tak:

SELECT FirstName, LastName
FROM   Person.Person
WHERE  FirstName = 'Jan' AND LastName = 'Kowalski' AND BusinessEntityID IN
                  (SELECT BusinessEntityID
                  FROM    HumanResources.Employee
                  WHERE   (JobTitle LIKE '%Vice President%'))
0

Oczywiście dla celów edukacyjnych użycie in nie jest złem, ale w systemach produkcyjnych jeśli zbiór zwracany przez podzapytanie użyte w in jest duży, lub duży jest zbiór, który ma zostać zawężony użycie in jest niezalecane, bo znacząco obniża wydajność. Lepiej przerobić zapytanie tak, aby użyć złączeń.

SELECT P.FirstName, P.LastName  FROM   Person.Person P
inner join (SELECT BusinessEntityID FROM    HumanResources.Employee WHERE   (JobTitle LIKE '%Vice President%')) as VP on P.BusinessEntityID = VP.BusinessEntityID
WHERE  P.FirstName = 'Jan' AND P.LastName = 'Kowalski'

lub często warto przed złączeniami zawęzić łączone zbiory jak się tylko da

select P.*
from (SELECT FirstName, LastName  FROM   Person.Person WHERE  P.FirstName = 'Jan' AND P.LastName = 'Kowalski') as P
inner join (SELECT BusinessEntityID FROM    HumanResources.Employee WHERE   (JobTitle LIKE '%Vice President%')) as VP on P.BusinessEntityID = VP.BusinessEntityID
0

A czemu taka kombinacja?

SELECT P.FirstName, P.LastName  FROM   Person.Person P
INNER JOIN (SELECT BusinessEntityID FROM    HumanResources.Employee WHERE   (JobTitle LIKE '%Vice President%')) AS VP ON P.BusinessEntityID = VP.BusinessEntityID
WHERE  P.FirstName = 'Jan' AND P.LastName = 'Kowalski'

??
Wydaje mi się (nie mam teraz możiwości sprawdzenia, że to będzie to samo co:

SELECT P.FirstName, P.LastName  FROM   Person.Person P
INNER JOIN HumanResources.Employee VP ON  VP.JobTitle LIKE '%Vice President%' AND P.BusinessEntityID = VP.BusinessEntityID
WHERE  P.FirstName = 'Jan' AND P.LastName = 'Kowalski'
0

Tą metodę znam, bo przerabiałem przed podzapytaniami. Chodzi mi tylko, czy dzięki podzapytaniom można wypisać kolumnę JobTitle, która pochodzi z tabeli podzapytania.

0

Tak.

SELECT P.*, VP.* -- to wypisze wszystkie kolumny z P i VP, ale nic nie stoi na przeszkodzie żeby podać tylko część, o które na nam chodzi, np. P.FirstName, P.LastName, VP.JobTitle
FROM (SELECT *  FROM   Person.Person WHERE  P.FirstName = 'Jan' AND P.LastName = 'Kowalski') AS P
INNER JOIN (SELECT * FROM    HumanResources.Employee WHERE   (JobTitle LIKE '%Vice President%')) AS VP ON P.BusinessEntityID = VP.BusinessEntityID

Musisz tylko pamiętać żeby podzapytania wybierały co najmniej te kolumny, które chcesz wybrać na wyższym poziomie.

@Marcin.Miga zasugerowałem zawężanie zbiorów przed łączeniem ponieważ często w ten sposób można znacząco zoptymalizować zapytanie. Oczywiście w tym przypadku przy złączeniu 2 tabel jeśli są one nieduże (kilka tys. rekordów) pewnie nie zauważymy specjalnej różnicy. Ale w zapytaniach gdzie musisz złączyć kilka, kilkanaście tabel (podzapytań) i połączyć, przefiltrować je po różnych warunkach, na dodatek kiedy tabele są duże (kilkaset tysięcy, kilka milionów rekordów) zawężanie zbiorów przed łączeniem odgrywa dużą rolę. To nie jest teoria, to są fakty z praktyki.
Oczywiście jak to w bazach danych, zawsze można powiedzieć to zależy... :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1