2010-08-05 58 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." 

線二號下面是一個以上錯誤失敗。我不明白爲什麼這個查詢沒有執行,因爲在第二行中不需要分組,因爲輸出只是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 
+0

什麼背後做一個COUNT(*),而不是COUNT(lpr.lessionplanid) – Perpetualcoder 2010-08-05 21:42:35

+0

由於內部查詢的輸出在從你的理由子句只是LessonPlanId字段,如果我沒有弄錯,它實際上和輸入count(lpr.lessionplanid)是一樣的。 – James 2010-08-05 21:53:43

回答

4

我的猜測是,@lessonPlanResources鏈接到LessonPlanId,這不是聚合。

我的解決方案是加入到該子表中,並將返回的列作爲COUNT。

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 2010-08-05 22:24:10

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(*)COUNT(*) OVER()

但是,這可能會給出多行結果,然後嘗試將其分配給一組標量變量。你想要做什麼

+0

+1按照您的建議在外部查詢的末尾添加一個組似乎可以解決問題。但從邏輯上講,我只是沒有看到這是多麼的合理。這只是這些供應商特定的問題之一嗎? – James 2010-08-05 21:51:40

+0

@詹姆斯 - MySQL不強制執行此操作,但所有其他人都這樣做。我想你仍然會遇到一個問題,儘管嘗試將多行寫入標量變量中(我想你可能只是最終會讓他們持有最後一組處理的值) – 2010-08-05 21:53:59

+0

我的意圖是隻能將聚合到不是行的變量中。 – James 2010-08-05 21:56:03

0

的問題是,你正在使用此子查詢分組功能(計數):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 
+0

謝謝,這是否表明我不再需要在from子句的內部查詢中完成獨特性,我期望dups? – James 2010-08-05 21:54:31

+0

不,它不是必要的,因爲任何愚蠢行爲都會被分組淘汰。 – kniemczak 2010-08-05 21:59:38

0
  • 刪除從外部選擇計數。
  • 在使用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

這似乎並不奏效。 – James 2010-08-05 22:04:29