2011-07-30 64 views
0

我的目標是編寫一個查詢,它將返回所有帶有3個標誌字段的類別,如下所示:是否可以在t-sql中對一個組進行子查詢?

ID | En | Ru | Fr

語言標誌必須根據是否與該類別關聯的任何課程記錄爲ON或OFF。

我現在的說法是這樣的:

SELECT c.ID, 
    (CASE WHEN c.ID IN (SELECT c.ID FROM Lessons AS l WHERE l.Category_Id = c.ID AND l.Language_Id = 1) THEN 1 ELSE 0 END) AS En, 
    (CASE WHEN c.ID IN (SELECT c.ID FROM Lessons AS l WHERE l.Category_Id = c.ID AND l.Language_Id = 2) THEN 1 ELSE 0 END) AS Ru, 
    (CASE WHEN c.ID IN (SELECT c.ID FROM Lessons AS l WHERE l.Category_Id = c.ID AND l.Language_Id = 3) THEN 1 ELSE 0 END) AS Fr 
FROM LessonCategories AS c 

的問題是,這個查詢是很慢的,因爲教訓表有超過60,000的記錄,我跑在它的3倍。

我正在尋找一種方法來提高此查詢的效率。 我曾想過在分類和課程之間使用分組,但我不知道具體如何以及是否有可能。

更多的快速查詢的僞代碼:

SELECT c.[ID], 
    COUNT(l.Language_Id = 1) > 0 AS En 
    COUNT(l.Language_Id = 2) > 0 AS Ru 
    COUNT(l.Language_Id = 3) > 0 AS Fr 
FROM CategoryTreeView AS c 
INNER JOIN Lessons AS l ON l.Category_Id = c.ID 
GROUP BY c.[ID] 

它可以表達這種使用有效的T-SQL? 或者是處理這種查詢的更好方法嗎?

P.S.如果有幫助,我不關心得到一個按位標誌字段而不是3個語言字段。

謝謝。

回答

1

那麼你剛纔給你的兩個查詢組合;)

SELECT c.ID, 
     SUM(case when l.Language_Id = 1 then 1 else 0) AS En 
     SUM(case when l.Language_Id = 2 then 1 else 0) AS Ru 
     SUM(case when l.Language_Id = 3 then 1 else 0) AS Fr 
FROM CategoryTreeView AS c 
INNER JOIN Lessons AS l ON l.Category_Id = c.ID 
GROUP BY c.ID 
+0

+1,你很可能忽略'CategoryTreeView'表作爲其任何領域都採用 – Andomar

+0

你是對的,我只需要每行的教訓表 –

0

嘗試這個

SELECT c.ID, 
    (CASE WHEN l.Language_Id = 1 THEN 1 ELSE 0 END) AS En, 
    (CASE WHEN l.Language_Id = 2 THEN 1 ELSE 0 END) AS Ru, 
    (CASE WHEN l.Language_Id = 3 THEN 1 ELSE 0 END) AS Fr 
FROM LessonCategories AS c 
INNER JOIN Lessons l ON c.ID = l.CategoryId 

BTW, 當前正在通過應用CASE報表做濾波SELECT條款。通過將篩選語句移動到在SELECT之前執行的WHERE子句,可以顯着提高任何查詢的性能。

0

您可以用數去你的第二個例子:

COUNT(case when l.Language_Id = 1 then 1 else null end) as EnCount 
COUNT(case when l.Language_Id = 2 then 1 else null end) as RuCount 

但實際上,要在使用exists你第一個例子:

case when exists(SELECT 0 FROM Lessons AS l WHERE l.Category_Id = c.ID AND l.Language_Id = 1) then 1 else 0 end as En 

通過適當的索引,三個exists s將muc h更快。

+0

一個索引查找比單個表掃描要慢得多。更不用說每行三次搜索! – Andomar

+0

@Andomar讓SQL Server決定。如果掃描結果變得更便宜,它將選擇執行「存在」的掃描。儘管如此,它將會是'存在',比'count'便宜。 – GSerg

+0

謝謝@GSerg,我將在兩個選項上運行基準測試 –

0

一個完全不同的方法嘗試透視。

DECLARE @ctw TABLE(id int, languageid int) 

insert @ctw values(1,1) 
insert @ctw values(1,1) 
insert @ctw values(1,2) 
insert @ctw values(1,3) 
insert @ctw values(2,1) 
insert @ctw values(2,3) 

SELECT * FROM 
(
SELECT id, CASE languageid WHEN 1 THEN 'en' WHEN 2 THEN 'ru' WHEN 3 THEN 'fr' END language 
FROM @ctw) a 
PIVOT 
(count(language) 
FOR language 
in([en],[ru],[fr]) 
)AS p ORDER BY id 

測試是在這裏http://data.stackexchange.com/stackoverflow/q/107960/

相關問題