2010-08-05 2 views
5

나는 다음과 같은 쿼리를 실행하기 위해 노력하고있어하지만 난 그것을 알리는 런타임 오류가 발생에서 단일 행 집계 하위 쿼리 문제 :SQL 고급 쿼리 - select 절

"The column is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause." 

행 번호 아래에 두 사람은 하나입니다 위의 오류로 실패합니다. 왜이 쿼리를 실행하지 않는 이유는 이해할 수 없다. 출력이 단지 카운트 (*) 일 뿐이므로, 내가이 작업을하기 위해 바꿀 필요가있는 어떤 단서가 있는가? Hogan 박사의 솔루션에 약간의 변화를 사용

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 
+0

뭐죠에서 내부 쿼리의 출력에서부터 카운트 (*)가 아닌 카운트 (lpr.lessionplanid) – Perpetualcoder

+0

을하고 뒤에 이유 절은 단지 LessonPlanId 필드입니다. 잘못 입력하지 않은 경우 count (lpr.lessionplanid)를 입력하는 것과 실제로 동일합니다. – James

답변

4

내 생각에 @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 
+0

좋은 움직임, 이것은 제가 사용을 끝내는 해결책이었습니다. – James

3

귀하의 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

당신은 GROUP BY a.LessonPlanId에 필요하고 아마도 당신이하려고하는 정확하게에 따라 COUNT(*) OVER()에 처음 COUNT(*)을 변경합니다.

하지만 아마도 단일 스칼라 변수 집합에 할당하려고하는 여러 행의 결과를 제공 할 것입니다. 은 정확히입니까?

+0

+1 제안한대로 외부 쿼리 끝에 그룹을 추가하면 문제를 해결하는 것으로 보입니다. 그러나 논리적으로 나는 그것이 어떤 의미인지를 단지 보지 않고있다. 이것은 벤더 고유의 잡아 당김 중 하나일까요? – James

+0

@James - MySQL은이를 시행하지 않지만 다른 모든 것은 수행합니다. 나는 당신이 비록 스칼라 변수에 여러 개의 행을 얻으려고 노력하면서도 여전히 문제가있을 것이라고 생각한다. (아마 마지막 그룹의 값을 유지하는 그들과 끝날 것 같아 보인다.) –

+0

내 의도는 행이 아닌 변수에 집계 만 가져옵니다. – James

0

문제는이 부질 함께 그룹화 함수 (COUNT)를 사용하는 점이다 lpr의 dbo.LessonPlanResource에서 선택 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 
+0

감사합니다. 더 이상 dup을 기대하는 from 절의 내부 쿼리에서 더 이상 별개의 작업을 수행 할 필요가 없다고 제안합니까? – James

+0

그룹에 의해 중복되지 않으므로 필요하지 않습니다. – kniemczak

0
  • 하여 외부 선택에서 COUNT 제거.
  • 에 DISTINCT COUNT를 사용하여 내부를 선택

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

이것은 작동하지 않습니다. – James