Tsql 可以在t-sql中对组进行子查询吗?

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

我的目标是编写一个查询,返回包含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.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