SQL сложный запрос - проблема с однострочным агрегатным подзапросом в предложении select - PullRequest
5 голосов
/ 06 августа 2010

Я пытаюсь выполнить следующий запрос, но получаю сообщение об ошибке во время выполнения, в котором говорится:

"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

[Редактировать]

Используя небольшое изменение решения Зеба - вот пересмотренный код, который я в итоге использовал, который дает одну строку с агрегатами, что и было после.

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

Ответы [ 5 ]

4 голосов
/ 06 августа 2010

Я думаю, что @lessonPlanResources связан с 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
3 голосов
/ 06 августа 2010

Ваш count(*) является агрегатной функцией, а выражение для @lessonPlanResources - нет (даже если это запрос с COUNT(*)).Поэтому выражение должно быть включено в предложение GROUP BY.

Вы можете использовать общие табличные выражения (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
1 голос
/ 06 августа 2010

Вам потребуется GROUP BY a.LessonPlanId и, возможно, изменить первое COUNT(*) на COUNT(*) OVER() в зависимости от того, что именно вы пытаетесь сделать.

Но это, вероятно, даст несколько строк результатов, которые вы затем пытаетесь присвоить одному набору скалярных переменных. Что вы пытаетесь сделать точно?

0 голосов
/ 06 августа 2010
  • Удаление COUNT из вашего внешнего выбора.
  • Использование COUNT DISTINCT в вашем внутреннем выборе

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
0 голосов
/ 06 августа 2010

Проблема в том, что вы используете функцию группировки (count) с этим подзапросом: SELECT COUNT (*) FROM dbo.LessonPlanResource lpr где 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...