Что за подзапрос вы имеете в виду?Что-то вроде:
SELECT t.TrackId,
t.[Name] AS Track,
(SELECT title FROM dbo.Album WHERE AlbumId = t.AlbumId) AS AlbumTitle
Это не пойдет, если вы удалите объединение для Album
, потому что вам нужна ссылка на альбом, чтобы добраться до исполнителя.Если вы хотите присоединиться к подзапросу, вы можете сделать это и сохранить псевдоним:
SELECT
t.TrackId,
t.[Name] AS Track,
a.Title AS Album,
aa.[Name] AS Artist,
p.[Name] AS Playlist,
m.[Name] AS MediaType,
il.UnitPrice AS InvoicePrice,
CONCAT(c.FirstName, ' ', c.LastName) AS CustomerName,
CONCAT(e.FirstName, ' ', e.LastName) AS ResponsibleEmployeeName
FROM dbo.Track AS t
INNER JOIN (SELECT * FROM dbo.Album) AS a
ON t.AlbumId = a.AlbumId
-- rest of joins
Но логически это точно так же, как у вас сейчас, и в плане не будет никакой разницыгенерируется оптимизатором запросов.Даже это:
SELECT
t.TrackId,
t.[Name] AS Track,
aa.Title AS Album, -- note change here
aa.[Name] AS Artist,
p.[Name] AS Playlist,
m.[Name] AS MediaType,
il.UnitPrice AS InvoicePrice,
CONCAT(c.FirstName, ' ', c.LastName) AS CustomerName,
CONCAT(e.FirstName, ' ', e.LastName) AS ResponsibleEmployeeName
FROM dbo.Track AS t
INNER JOIN (SELECT alb.Title
, art.Name
, alb.AlbumId
FROM dbo.Album alb
INNER JOIN dbo.Artist art
ON art.ArtistId = alb.ArtistID) AS aa
ON t.AlbumId = aa.AlbumId
INNER JOIN dbo.PlaylistTrack AS plt
ON t.TrackId = plt.TrackId
-- rest of them
Будет производить точно такой же план.Мы могли бы переместить Album
<-> Artist
присоединение к присоединенному подзапросу, но, по сути, это то же самое - внутренние объединения.
Ничего подобного не поможет в вашей работе.Что может помочь вам - это создать индексы для этих таблиц.Если этот тип запроса вы выполняете много, вы также можете создать индексированное представление, например:
CREATE VIEW BoughtTracks
WITH SCHEMABINDING
AS
SELECT
il.InvoiceLineId, -- I'm guessing here, we need a unique ID
t.TrackId,
t.[Name] AS Track,
a.Title AS Album,
aa.[Name] AS Artist,
p.[Name] AS Playlist,
m.[Name] AS MediaType,
il.UnitPrice AS InvoicePrice,
CONCAT(c.FirstName, ' ', c.LastName) AS CustomerName,
CONCAT(e.FirstName, ' ', e.LastName) AS ResponsibleEmployeeName
FROM dbo.Track AS t
INNER JOIN dbo.Album AS a
ON t.AlbumId = a.AlbumId
INNER JOIN dbo.Artist AS aa
ON a.ArtistId = aa.ArtistId
INNER JOIN dbo.PlaylistTrack AS plt
ON t.TrackId = plt.TrackId
INNER JOIN dbo.Playlist AS p
ON p.PlaylistId = plt.PlaylistId
INNER JOIN dbo.MediaType AS m
ON t.MediaTypeId = m.MediaTypeId
INNER JOIN dbo.InvoiceLine AS il
ON t.TrackId = il.TrackId
INNER JOIN dbo.Invoice AS i
ON il.InvoiceId = i.InvoiceId
INNER JOIN dbo.Customer AS c
ON i.CustomerId = c.CustomerId
INNER JOIN dbo.Employee AS e
ON c.SupportRepId = e.EmployeeId
WHERE m.[Name] LIKE '%audio%'
CREATE UNIQUE CLUSTERED INDEX ux ON BoughtTracks (InvoiceLineId);
Это замедлит вставки в эти таблицы, но выбор на BoughtTracks
будет быстрым(вы также можете создавать дополнительные индексы для этого представления), например:
SELECT *
FROM BoughtTracks WITH (NOEXPAND) -- NOEXPAND is important
WHERE CustomerName = 'Joe Smith'
Может выполнять на несколько порядков быстрее, чем ваш текущий запрос, в зависимости, конечно, от размера ваших данных.Особенно, если вы создаете индекс для него
CREATE INDEX ix_CustomerName ON BoughtTracks (CustomerName)
INCLUDE (...) -- maybe include some columns you know you will need when querying for CustomerName
WHERE (...) -- maybe there are alsways accompanying predicates when querying for CustomerName