错误:"在包含外部引用的聚合表达式中指定了多个列。"

时间:2014-10-23 17:56:41

标签: sql sql-server tsql aggregation

您好我在尝试执行以下查询时收到此错误。有什么想法或建议吗?

错误:"在包含外部引用的聚合表达式中指定了多个列。如果聚合的表达式包含外部引用,则该外部引用必须是表达式中引用的唯一列。"

SELECT TestInstances.pkTestInstanceID AS 'pkTestInstanceID',
               bands.pkPerformanceLevelReportBandID AS 'BandID',
               bands.StackPosition AS 'StackPosition',
               (SELECT TOP 100 PERCENT SUM(CASE WHEN bands.StackPosition = b.StackPosition THEN 1 ELSE 0 END) * 100/ CASE WHEN COUNT(StudentScores_Subject.pkStudentScoreID) = 0 THEN 1 ELSE COUNT(StudentScores_Subject.pkStudentScoreID) END
                FROM PerformanceLevelReportBands b 
                WHERE b.fkPerformanceLevelReportID = @intPerfLevelReportId
                ORDER BY SUM(CASE WHEN bands.StackPosition = b.StackPosition THEN 1 ELSE 0 END) * 100/ CASE WHEN COUNT(StudentScores_Subject.pkStudentScoreID) = 0 THEN 1 ELSE COUNT(StudentScores_Subject.pkStudentScoreID) END) AS 'Percent',
         COUNT(StudentScores_Subject.pkStudentScoreID) AS 'Count'
         FROM StudentScores_Subject
                INNER JOIN StudentTests ON StudentScores_Subject.fkStudentTestID = StudentTests.pkStudentTestID
                INNER JOIN TestInstances ON  TestInstances.pkTestInstanceID = StudentTests.fkTestInstanceID
                INNER JOIN CAHSEE_TestPeriods ON CAHSEE_TestPeriods.pkTestPeriodID = TestInstances.fkTestPeriodID
                INNER JOIN PerformanceLevelReportBands bands ON bands.fkPerformanceLevelReportID = @intPerfLevelReportId
                LEFT JOIN MMARS_Web_TestInfo_California.dbo.PerfLevelReportBandCutScores cutScores ON cutScores.fkPerformanceLevelReportBandID = bands.pkPerformanceLevelReportBandID
                    AND cutScores.fkGradeID = @intGradeId
                    AND cutScores.fkTestSubjectID IN (SELECT id FROM @tempSubs)
                INNER JOIN PerfLevelReportBandComponents bandComponents ON bandComponents.fkPerformanceLevelReportBandID = bands.pkPerformanceLevelReportBandID 
                    AND((bandComponents.ScoreValue = StudentScores_Subject.ScoreValue) OR 
                        ((CAST(StudentScores_Subject.ScoreValue AS INT) BETWEEN bandComponents.minScore and bandComponents.maxScore)
                          OR 
                         (CAST(StudentScores_Subject.ScoreValue AS INT) BETWEEN cutScores.minScore and cutScores.maxScore)))
                RIGHT JOIN MM_SchoolYears ON MM_SchoolYears.pkSchoolYearID = TestInstances.fkSchoolYearID
        WHERE MM_SchoolYears.pkSchoolYearID IN (SELECT number FROM itot(@strYearIds, N','))
                AND StudentScores_Subject.fkStudentTestID IN (SELECT id FROM @tempTests)
                AND StudentScores_Subject.fkScoreTypeID = bandComponents.fkScoreTypeID
                AND StudentScores_Subject.fkTest_SubjectID IN (SELECT id FROM @tempSubs)
        GROUP BY TestInstances.pkTestInstanceID, bands.pkPerformanceLevelReportBandID, bands.StackPosition
        ORDER BY TestInstances.pkTestInstanceID, bands.pkPerformanceLevelReportBandID, bands.StackPosition

3 个答案:

答案 0 :(得分:5)

问题在于你无法在聚合函数

中组合外部和内部引用
(SELECT TOP 100 PERCENT SUM(CASE WHEN bands.StackPosition = b.StackPosition THEN 1 ELSE 0 END) * 100/ CASE

WHEN COUNT(StudentScores_Subject.pkStudentScoreID) = 0 THEN 1

ELSE COUNT(StudentScores_Subject.pkStudentScoreID)

 END
   FROM PerformanceLevelReportBands b
   WHERE b.fkPerformanceLevelReportID = @intPerfLevelReportId
   ORDER BY SUM(CASE WHEN bands.StackPosition = b.StackPosition THEN 1 ELSE 0 END) * 100/ CASE

WHEN COUNT(StudentScores_Subject.pkStudentScoreID) = 0 THEN 1

ELSE COUNT(StudentScores_Subject.pkStudentScoreID)

END) AS 'Percent'

所以将其改为

(SELECT TOP 100 PERCENT SUM(CASE WHEN bb.StackPosition = b.StackPosition THEN 1 ELSE 0 END) * 100/ CASE

  WHEN COUNT(StudentScores_Subject.pkStudentScoreID) = 0 THEN 1

  ELSE COUNT(StudentScores_Subject.pkStudentScoreID)

 END
   FROM PerformanceLevelReportBands b JOIN PerformanceLevelReportBands bb
    ON bb.fkPerformanceLevelReportID =bands.fkPerformanceLevelReportID 
    AND b.fkPerformanceLevelReportID =bb.fkPerformanceLevelReportID
   WHERE b.fkPerformanceLevelReportID = @intPerfLevelReportId
   ORDER BY SUM(CASE WHEN bb.StackPosition = b.StackPosition THEN 1 ELSE 0 END) * 100/ CASE

 WHEN COUNT(StudentScores_Subject.pkStudentScoreID) = 0 THEN 1

 ELSE COUNT(StudentScores_Subject.pkStudentScoreID)

 END) AS 'Percent'

这是更多thorough explanation

答案 1 :(得分:0)

我建议评论bandComponents然后cutScores,在删除每个组件后重新运行并查看查询失败的位置。一旦你找出它失败的地方,你就可以解决它。

此外,可能是此行,即您的百分比列中的查询。

ORDER BY SUM(CASE WHEN bands.StackPosition = b.StackPosition THEN 1 ELSE 0 END) * 100 

我尝试更好地整理您的查询,以使其更清晰。

SELECT 
    TestInstances.pkTestInstanceID                      AS 'pkTestInstanceID'
    , bands.pkPerformanceLevelReportBandID              AS 'BandID'
    , bands.StackPosition                               AS 'StackPosition'
    , (
        SELECT TOP 100 PERCENT 
            SUM( CASE 
                    WHEN bands.StackPosition = b.StackPosition 
                    THEN 1 
                    ELSE 0 
                    END) * 100 / 
                CASE 
                    WHEN COUNT(StudentScores_Subject.pkStudentScoreID) = 0 
                    THEN 1 
                    ELSE COUNT(StudentScores_Subject.pkStudentScoreID) 
                    END
            FROM PerformanceLevelReportBands b 
            WHERE b.fkPerformanceLevelReportID = @intPerfLevelReportId
            ORDER BY SUM(CASE WHEN bands.StackPosition = b.StackPosition THEN 1 ELSE 0 END) * 100 
            / 
            CASE 
                WHEN COUNT(StudentScores_Subject.pkStudentScoreID) = 0 
                THEN 1 
                ELSE COUNT(StudentScores_Subject.pkStudentScoreID) 
                END
            )                                           AS 'Percent'
    , COUNT(StudentScores_Subject.pkStudentScoreID)     AS 'Count'
 FROM 
    StudentScores_Subject
INNER JOIN 
    StudentTests ON 
    StudentScores_Subject.fkStudentTestID = StudentTests.pkStudentTestID
INNER JOIN 
    TestInstances ON 
    TestInstances.pkTestInstanceID = StudentTests.fkTestInstanceID
INNER JOIN 
    CAHSEE_TestPeriods ON 
    CAHSEE_TestPeriods.pkTestPeriodID = TestInstances.fkTestPeriodID
INNER JOIN 
    PerformanceLevelReportBands bands ON 
    bands.fkPerformanceLevelReportID = @intPerfLevelReportId
LEFT JOIN 
    MMARS_Web_TestInfo_California.dbo.PerfLevelReportBandCutScores cutScores ON 
        cutScores.fkPerformanceLevelReportBandID = bands.pkPerformanceLevelReportBandID
    AND cutScores.fkGradeID = @intGradeId
    AND cutScores.fkTestSubjectID IN (SELECT id FROM @tempSubs)
INNER JOIN 
    PerfLevelReportBandComponents bandComponents ON 
    bandComponents.fkPerformanceLevelReportBandID = bands.pkPerformanceLevelReportBandID 
    AND(
        (bandComponents.ScoreValue = StudentScores_Subject.ScoreValue) OR 
        (
            (CAST(StudentScores_Subject.ScoreValue AS INT) BETWEEN bandComponents.minScore and bandComponents.maxScore) OR 
            (CAST(StudentScores_Subject.ScoreValue AS INT) BETWEEN cutScores.minScore and cutScores.maxScore)
         )
        )
RIGHT JOIN 
    MM_SchoolYears ON 
    MM_SchoolYears.pkSchoolYearID = TestInstances.fkSchoolYearID
WHERE 
        MM_SchoolYears.pkSchoolYearID IN (SELECT number FROM itot(@strYearIds, N','))
    AND StudentScores_Subject.fkStudentTestID IN (SELECT id FROM @tempTests)
    AND StudentScores_Subject.fkScoreTypeID = bandComponents.fkScoreTypeID
    AND StudentScores_Subject.fkTest_SubjectID IN (SELECT id FROM @tempSubs)
GROUP BY TestInstances.pkTestInstanceID, bands.pkPerformanceLevelReportBandID, bands.StackPosition
ORDER BY TestInstances.pkTestInstanceID, bands.pkPerformanceLevelReportBandID, bands.StackPosition

答案 2 :(得分:0)

我遇到了相同的问题或类似的问题。 为了帮助您,我在这里留下了初始代码和解决方案。

初始代码:

SELECT ISNULL((SELECT DateName(mm,DATEADD(mm,Perioada - 1,0))),'Nedefinit') as [Period],MAX(t.TipPerioada) AS TipPerioada,t.Perioada,MAX(t.An) AS An, a.NumePrenume, CAST(t.Volum as float) as ValTip,
            ISNULL((Select Sum(v.Cantitate*p.VolumProdus)
                    From Wme_Vanzari as v 
                    WHERE ('ND'='ND' or v.MarcaAgent = t.MarcaAgent) and  t.[An]=v.AnFactura  and t.Perioada=v.Lunafactura),0) as Realizat,
            '' as Diferenta,'' as DiferentaWD,'' as Procent
            FROM  [Memo_Target] t
            --Aduce Suma de Cantitate si MarcaAgent pentru a nu dubla cu liniile din Vanzari 
            LEFT JOIN (Select SUM(Cantitate) as Cantitate, MarcaAgent 
                        From Wme_Vanzari  
                        WHERE AnFactura = @An 
                        GROUP BY MarcaAgent) v on t.MarcaAgent = v.MarcaAgent
            LEFT JOIN WME_Agenti a on a.Marca = t.MarcaAgent
            --Aduce Suma de VolumProdus, CodProdus si Marca Agent Filtrat dupa Anul dat in parametru, Volum necesar pt a calcula Realizat si a scade din targetul setat
            LEFT JOIN  (SELECT SUM(ISNULL(n.VolumProdus, 0)) AS VolumProdus, v.CodProdus, v.MarcaAgent
                        FROM Wme_NomenclatorProduse n
                        LEFT JOIN Wme_Vanzari v ON v.CodProdus = n.CodIntern
                        WHERE v.MarcaAgent IS NOT NULL AND v.CodProdus IS NOT NULL  AND v.AnFactura = @An
                        GROUP BY v.CodProdus, v.MarcaAgent  ) p ON p.MarcaAgent = t.MarcaAgent
            WHERE (t.Volum IS NOT NULL AND t.Volum > 0)
            AND t.An = @An
            AND (CAST(t.Perioada AS INT) BETWEEN @lunastart AND @lunaend)
            AND TipTarget = @tiptarget
            AND (a.Marca IN (SELECT * FROM dbo.GetIdsTableString(@marcaAgent)) OR @marcaAgent = 'ND')
            GROUP BY a.NumePrenume, t.Volum, Perioada,t.An

错误消息是相同的,这是解决方法代码:

SELECT ISNULL((SELECT DateName(mm,DATEADD(mm,Perioada - 1,0))),'Nedefinit') as [Period],MAX(t.TipPerioada) AS TipPerioada,t.Perioada,MAX(t.An) AS An, a.NumePrenume, CAST(t.Volum as float) as ValTip,
            (ISNULL((Select Sum(p.VolumProdus)
                    From Wme_Vanzari as v 
                    WHERE ('ND'='ND' or v.MarcaAgent = t.MarcaAgent) and  t.[An]=v.AnFactura  and t.Perioada=v.Lunafactura),0) * sum(v.Cantitate)) as Realizat,
            '' as Diferenta,'' as DiferentaWD,'' as Procent
            FROM  [Memo_Target] t
            --Aduce Suma de Cantitate si MarcaAgent pentru a nu dubla cu liniile din Vanzari 
            LEFT JOIN (Select SUM(Cantitate) as Cantitate, MarcaAgent 
                        From Wme_Vanzari  
                        WHERE AnFactura = @An 
                        GROUP BY MarcaAgent) v on t.MarcaAgent = v.MarcaAgent
            LEFT JOIN WME_Agenti a on a.Marca = t.MarcaAgent
            --Aduce Suma de VolumProdus, CodProdus si Marca Agent Filtrat dupa Anul dat in parametru, Volum necesar pt a calcula Realizat si a scade din targetul setat
            LEFT JOIN  (SELECT SUM(ISNULL(n.VolumProdus, 0)) AS VolumProdus, v.CodProdus, v.MarcaAgent
                        FROM Wme_NomenclatorProduse n
                        LEFT JOIN Wme_Vanzari v ON v.CodProdus = n.CodIntern
                        WHERE v.MarcaAgent IS NOT NULL AND v.CodProdus IS NOT NULL  AND v.AnFactura = @An
                        GROUP BY v.CodProdus, v.MarcaAgent  ) p ON p.MarcaAgent = t.MarcaAgent
            WHERE (t.Volum IS NOT NULL AND t.Volum > 0)
            AND t.An = @An
            AND (CAST(t.Perioada AS INT) BETWEEN @lunastart AND @lunaend)
            AND TipTarget = @tiptarget
            AND (a.Marca IN (SELECT * FROM dbo.GetIdsTableString(@marcaAgent)) OR @marcaAgent = 'ND')
            GROUP BY a.NumePrenume, t.Volum, Perioada,t.An

如您所见,我选择在第一个子选择中保留一列,并且在此子选择后我被迫使用乘法运算。 希望对您有所帮助!