SQL高级查询-select子句中的单行聚合子查询存在问题

SQL高级查询-select子句中的单行聚合子查询存在问题,sql,sql-server-2008,Sql,Sql Server 2008,我正在尝试执行以下查询,但收到一个运行时错误,指出: "The column is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause." 下面的第二行是由于上述错误而失败的行。我不明白为什么这个查询没有执行,因为第二行中不需要分组,因为输出只是count(*),关于我需要更改什么以使其工作的任何线索 SELECT @lesso

我正在尝试执行以下查询,但收到一个运行时错误,指出:

"The column is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause."
下面的第二行是由于上述错误而失败的行。我不明白为什么这个查询没有执行,因为第二行中不需要分组,因为输出只是count(*),关于我需要更改什么以使其工作的任何线索

SELECT @lessonPlans = COUNT(*)
, @lessonPlanResources = (SELECT COUNT(*) FROM dbo.LessonPlanResource lpr where lpr.LessonPlanId = a.LessonPlanId )
FROM
( 
    SELECT DISTINCT lpt.LessonPlanId
    FROM dbo.LearningTargetBreakout ltb
    JOIN dbo.LessonPlanLearningTarget lpt 
        on lpt.LearningTargetId = ltb.LearningTargetId
    WHERE (CASE 
            WHEN ltb.LearningTargetId = @learningTargetId and @learningTargetId is not null THEN 1
            WHEN ltb.CategoryId = @categoryId and @categoryId is not null THEN 1
            WHEN ltb.Grade = @grade and @grade is not null THEN 1
            WHEN ltb.SubjectId = @subjectId and @subjectId is not null THEN 1
            ELSE 0 END) = 1
) a
[编辑]

使用Zeb的解决方案的一个微小变化-这里是我最终使用的修订代码,它生成一行集合,这就是我所追求的

SELECT @lessonPlans = ISNULL(COUNT(*), 0)
        , @lessonPlanResources = ISNULL(SUM(a.ResCount), 0)
FROM
( 
    SELECT DISTINCT lpt.LessonPlanId, lpr.ResCount
    FROM dbo.LearningTargetBreakout ltb
    JOIN dbo.LessonPlanLearningTarget lpt 
        on lpt.LearningTargetId = ltb.LearningTargetId
    JOIN (SELECT LessonPlanId, COUNT(*) ResCount FROM dbo.LessonPlanResource lpr GROUP BY LessonPlanId) lpr
        ON lpr.LessonPlanId = lpt.LessonPlanId          
    WHERE (CASE 
            WHEN ltb.LearningTargetId = @learningTargetId and @learningTargetId is not null THEN 1
            WHEN ltb.CategoryId = @categoryId and @categoryId is not null THEN 1
            WHEN ltb.GradeId = @grade and @grade is not null THEN 1
            WHEN ltb.SubjectId = @subjectId and @subjectId is not null THEN 1
            ELSE 0 END) = 1
) a
您的
count(*)
是一个聚合函数,@lessonPlanResources的表达式不是(即使它是一个带有
count(*)
的查询)。因此,表达式必须包含在GROUPBY子句中

您可以使用公共表表达式(CTE),这也有助于提高可读性

WITH LPR_CTE as
    (
    SELECT LessonPlanId, COUNT(*) as LessonPlanResourcesCount
    FROM dbo.LessonPlanResource
    GROUP BY LessonPlanId
    ),

    LP_CTE(
    SELECT lpt.LessonPlanId, COUNT(*) as LessonPlansCount
    FROM dbo.LearningTargetBreakout ltb
    JOIN dbo.LessonPlanLearningTarget lpt 
        on lpt.LearningTargetId = ltb.LearningTargetId
    WHERE (CASE 
            WHEN ltb.LearningTargetId = @learningTargetId and @learningTargetId is not null THEN 1
            WHEN ltb.CategoryId = @categoryId and @categoryId is not null THEN 1
            WHEN ltb.Grade = @grade and @grade is not null THEN 1
            WHEN ltb.SubjectId = @subjectId and @subjectId is not null THEN 1
            ELSE 0 END) = 1
    )

SELECT @lessonPlans = LP_CTE.LessonPlansCount
     , @lessonPlanResources = LPR_CTE.LessonPlanResourcesCount
FROM LP_CTE
JOIN LPR_CTE on LP_CTE.LessonPlanId = LPR_CTE.LessonPlanId

您需要根据a.LessonPlanId对
进行分组
,并可能将第一个
COUNT(*)
更改为
COUNT(*)OVER()
,具体取决于您正试图执行的操作


但这可能会给出多行结果,然后您试图将这些结果分配给单个标量变量集。你到底想做什么?

我猜@lessonPlanResources链接到LessonPlanId,而LessonPlanId不是聚合的

我的解决方案是连接到该子表,并将返回的列作为其计数

SELECT @lessonPlans = COUNT(*)
, @lessonPlanResources = SUM(zlpr.reses)
FROM
( 
    SELECT DISTINCT lpt.LessonPlanId, zlpr.reses
    FROM dbo.LearningTargetBreakout ltb
    JOIN dbo.LessonPlanLearningTarget lpt 
        on lpt.LearningTargetId = ltb.LearningTargetId
    JOIN (SELECT LessonPlanId, COUNT(*) reses FROM dbo.LessonPlanResource lpr) zlpr
        ON zlpr.LessonPlanId = lpt.LessonPlanId
    WHERE (CASE 
            WHEN ltb.LearningTargetId = @learningTargetId and @learningTargetId is not null THEN 1
            WHEN ltb.CategoryId = @categoryId and @categoryId is not null THEN 1
            WHEN ltb.Grade = @grade and @grade is not null THEN 1
            WHEN ltb.SubjectId = @subjectId and @subjectId is not null THEN 1
            ELSE 0 END) = 1
) a

问题是您正在使用分组函数(count)与此子查询:从dbo.lessonplansource lpr中选择count(*),其中lpr.LessonPlanId=a.LessonPlanId

但是,对a.LessonPlanId的引用是一个非分组字段。对查询进行分组,可以引用该字段

试试这个:

SELECT @lessonPlans = COUNT(*)
, @lessonPlanResources = (SELECT COUNT(*) FROM dbo.LessonPlanResource lpr where lpr.LessonPlanId = a.LessonPlanId )
FROM
( 
    SELECT DISTINCT lpt.LessonPlanId
    FROM dbo.LearningTargetBreakout ltb
    JOIN dbo.LessonPlanLearningTarget lpt 
        on lpt.LearningTargetId = ltb.LearningTargetId
    WHERE (CASE 
            WHEN ltb.LearningTargetId = @learningTargetId and @learningTargetId is not null THEN 1
            WHEN ltb.CategoryId = @categoryId and @categoryId is not null THEN 1
            WHEN ltb.Grade = @grade and @grade is not null THEN 1
            WHEN ltb.SubjectId = @subjectId and @subjectId is not null THEN 1
            ELSE 0 END) = 1
) a
GROUP BY a.LessonPlanID
  • 从外部选择中删除计数
  • 在内部选择中使用COUNT DISTINCT


既然from子句中内部查询的输出只是LessonPlanId字段,那么执行count(*)和not count(lpr.lessionplanid)的原因是什么?如果我没有弄错的话,它实际上与键入count(lpr.lessionplanid)是一样的。+1按照您的建议在外部查询的末尾添加group by似乎可以解决问题。但从逻辑上讲,我只是不明白这有什么意义。这只是那些特定于供应商的问题之一吗?@James-MySQL不强制执行这一点,但其他所有人都强制执行。不过,我认为您在尝试将多行放入标量变量时仍然会遇到问题(我猜您可能最终会将它们保留最后一个处理组的值)我的目的是只将聚合提取到变量中,而不是行中。@James-如果您像直接的
SELECT
一样运行查询,而不指定变量,那么您应该会看到多行(每个LessonPlanId对应一行)。在变量末尾的任何一个结尾都是任意的,只取决于组的处理顺序。我怀疑这可能是我的意图?你是对的,我认为我需要彻底重新考虑我在这一点上的策略…谢谢,这是否意味着我不再需要在from子句的内部查询中进行distinct,在那里我期望DUP?不,这没有必要,因为任何DUP都会被分组消除。动作不错,这就是我最终使用的解决方案。
SELECT 
   @lessonPlans = a.B,
   @lessonPlanResources = (SELECT COUNT(*) FROM dbo.LessonPlanResource lpr where lpr.LessonPlanId = a.LessonPlanId )
FROM
( 
    SELECT COUNT (DISTINCT, lpt.LessonPlanId) AS B
    FROM dbo.LearningTargetBreakout ltb
    JOIN dbo.LessonPlanLearningTarget lpt 
        on lpt.LearningTargetId = ltb.LearningTargetId
    WHERE (CASE 
            WHEN ltb.LearningTargetId = @learningTargetId and @learningTargetId is not null THEN 1
            WHEN ltb.CategoryId = @categoryId and @categoryId is not null THEN 1
            WHEN ltb.Grade = @grade and @grade is not null THEN 1
            WHEN ltb.SubjectId = @subjectId and @subjectId is not null THEN 1
            ELSE 0 END) = 1
) a