Pytanie odnośnie podzapytań (MS SQL Server)

Pytanie odnośnie podzapytań (MS SQL Server)
  • Rejestracja: dni
  • Ostatnio: dni
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ć?

Kopiuj
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 ;)

scovron
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 27
0

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

Kopiuj
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%'))
massther
  • Rejestracja: dni
  • Ostatnio: dni
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ń.

Kopiuj
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

Kopiuj
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
Marcin.Miga
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2794
0

A czemu taka kombinacja?

Kopiuj
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:

Kopiuj
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'
  • Rejestracja: dni
  • Ostatnio: dni
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.

massther
  • Rejestracja: dni
  • Ostatnio: dni
0

Tak.

Kopiuj
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... :)

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.