2011-04-19 124 views
1

我有以下的疑問,我很想找到一個更好的辦法來做到這一點,因爲它看起來不正確我這樣做的方式......SQL Server查詢優化問題

編輯

對不起,我沒有指定我只想返回實際匹配所有設施的廣告!

SELECT TOP 50 Advert.Id 
FROM Advert 
WHERE Id in(SELECT Advert_id FROM AdvertsToAmenities WHERE Amenity_id = 1 AND Advert_Id = Id) 
    AND Id in(SELECT Advert_id FROM AdvertsToAmenities WHERE Amenity_id = 3 AND Advert_Id = Id) 
    AND Id in(SELECT Advert_id FROM AdvertsToAmenities WHERE Amenity_id = 5 AND Advert_Id = Id) 

-- OR -- 

SELECT TOP 50 Advert.Id 
FROM Advert 
JOIN AdvertsToAmenities a on Advert.Id = a.Advert_id 
JOIN AdvertsToAmenities b on Advert.Id = b.Advert_id 
JOIN AdvertsToAmenities c on Advert.Id = c.Advert_id 
WHERE a.Amenity_id = 1 
    AND b.Amenity_id = 3 
    AND c.Amenity_id = 5 

我想知道如何優化這些查詢!

+1

「要做到這一點」 - 你能不能給我們一個很好的解決問題的說明,而不必大家一起讀書的問題解析查詢? – Oded 2011-04-19 15:24:56

+1

看起來你的問題與你的評論不一樣。請記住,SQL Server從查詢中派生出的執行路徑是高度優化的,儘管您聲明SQL的順序方式。可能需要檢查實際執行計劃以確定是否需要進一步優化。 如果你指的是讓sql更易讀易懂,那麼顯然有改進的餘地。我會試着拿出一個例子。 – 2011-04-19 15:27:24

+0

此外,您可能會發現表格中體面的索引/鍵會比重新編寫查詢有更戲劇性的「優化」結果。 – 2011-04-19 15:30:14

回答

3

您的問題對我來說看起來不錯。另一種方法是使用這樣的:

SELECT TOP 50 Advert.Id 
    FROM Advert JOIN AdvertsToAmenities a ON Advert.Id = a.Advert_id 
WHERE a.Amenity_id = 1 
    OR a.Amenity_id = 3 
    OR a.Amenity_id = 5 
GROUP BY Advert.Id 
HAVING COUNT(DISTINCT a.Amenity_id) = 3 

如果(Advert_Id, Amenity_id)對都是獨一無二的,你可以刪除DISTINCT

+0

+1 - 我認爲他的原稿也不錯。 – JNK 2011-04-19 15:27:31

0

你的查詢如何重組,可以讓你簡單地創建一個逗號分隔的特定設施ID的列表?

SELECT TOP 50 
a.[ID] 
FROM [Advert] a 
INNER JOIN 
(
    SELECT ata.[Advert_ID] 
    FROM [AdvertsToAmenities] ata 
    WHERE ata.[Amenity_ID] 
    IN (1, 3, 4, 5) -- Your list of amenity IDs 
) as ata 
ON a.[ID] = ata.[Advert_ID] 

這使用動態表語句在與廣告列表進行回合之前僅對那些適用的設施進行預先過濾。請注意,Sql Server將在執行之前大量優化子查詢。這應該意味着您將得到Sql Server提供的所有優化的更多可維護語句的好處。

+0

我只想返回他們在列表中具有*全部*設施的廣告。在您的查詢中,它將返回至少有一個*列表中的設施的廣告。 – superlogical 2011-04-21 07:33:14

0

*試試這個簡單的*

SELECT TOP 50 a.Id 
FROM Advert a, AdvertsToAmenities b 
WHERE a.Amenity_id in ('1','3','5') 
and a.Id = b.Amenity_id