我的目标是编写一个查询,返回包含3个标志字段的所有类别,如下所示:
ID |恩|茹| 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
问题是这个查询非常慢,因为Lessons表有超过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个语言字段。
感谢。
答案 0 :(得分: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
答案 1 :(得分: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
顺便说一句,
目前,您正在通过应用SELECT
语句对CASE
子句进行过滤。通过将过滤语句移动到WHERE
之前执行的SELECT
子句,可以显着提高任何查询的性能。
答案 2 :(得分: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
将更快。
答案 3 :(得分: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