Tsql 可以在t-sql中对组进行子查询吗?
我的目标是编写一个查询,返回包含3个标志字段的所有类别,如下所示: ID | En | Ru | Fr 语言标志必须根据是否有与类别关联的任何课程记录打开或关闭 我目前的声明如下:Tsql 可以在t-sql中对组进行子查询吗?,tsql,group-by,subquery,Tsql,Group By,Subquery,我的目标是编写一个查询,返回包含3个标志字段的所有类别,如下所示: ID | En | Ru | Fr 语言标志必须根据是否有与类别关联的任何课程记录打开或关闭 我目前的声明如下: 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
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表有60000多条记录,我对它运行了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来表示这一点?
还是有更好的方法来处理这种查询
如果有帮助的话,我不想得到一个按位标志字段而不是3个语言字段
谢谢。试试这个
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
顺便说一句,
当前,您正在通过应用
CASE
语句在SELECT
子句中进行筛选。通过将筛选语句移动到WHERE
子句,您可以显著提高任何查询的性能,该子句在SELECT
之前执行。您只需将两个查询组合起来即可;)
您可以在第二个示例中使用计数:
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
有了适当的索引,三个
存在
会快得多。一个完全不同的方法
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
Test在这里+1,您可能会忽略
CategoryTreeView
表,因为它的任何字段都不可用。每行的索引查找速度比单个表扫描慢得多。更不用说每行三次了@Andomar让SQL Server来决定。如果扫描结果更便宜,它将选择一个扫描来执行exists
。不过,它将是存在的
,这比计数
更便宜。
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