2010-08-05 15 views
5

Estoy tratando de ejecutar la siguiente consulta pero recibo un error de ejecución indicando que:consulta SQL avanzado - un problema con una sola fila agregada sub consulta en la cláusula select

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

número dos por debajo de la línea es la que falla con el error anterior. No entiendo por qué esta consulta no se ejecuta, ya que no debe requerirse ninguna agrupación en la línea dos, ya que el resultado es simplemente contar (*), ¿hay alguna pista sobre lo que necesito cambiar para que funcione?

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 

[Editar]

Usando una ligera variación de la solución de Zeb - Este es el código revisado que Terminé usando, lo que da una hilera con agregados, que es lo que estaba buscando.

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

cuál es la razón detrás de hacer un recuento (*) y no contar (lpr.lessionplanid) – Perpetualcoder

+0

Desde la salida de la consulta interna en el de cláusula es solo el campo LessonPlanId, en realidad es lo mismo que typing out count (lpr.lessionplanid) si no me equivoco. – James

Respuesta

4

Supongo que el @lessonPlanResources está vinculado al LessonPlanId, que no es agregado.

Mi solución sería UNIRSE a esa subtabla y hacer que la columna devuelta sea un COUNT de ella.

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

Movimientos agradables, esta fue la solución que terminé usando. – James

3

Su count(*) es una función de agregado y la expresión de @lessonPlanResources no es (a pesar de que se trata de una consulta con COUNT(*)). Por lo tanto, la expresión debe incluirse en la cláusula GROUP BY.

Puede usar expresiones de tabla comunes (CTE), que también pueden ayudar con la legibilidad.

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

Usted tendría que GROUP BY a.LessonPlanId y posiblemente cambiar el primer COUNT(*)-COUNT(*) OVER() dependiendo de qué es exactamente lo que está intentando hacer.

Pero eso presumiblemente dará varias filas de resultados que luego intenta asignar a un solo conjunto de variables escalares. ¿Qué están tratando de hacer exactamente?

+0

+1 Agregar un grupo al final de la consulta externa como sugirió parece solucionar el problema. Pero, lógicamente, simplemente no veo cómo tiene sentido. ¿Es solo uno de esos gotcha específicos del proveedor? – James

+0

@James - MySQL no hace cumplir esto, pero todos los demás lo hacen. Sin embargo, creo que todavía vas a tener un problema al tratar de obtener varias filas en la variable escalar (supongo que probablemente termines con el valor del último grupo procesado) –

+0

Mi intención era solo obtener agregados en las variables, no en las filas. – James

0

La cuestión es que está utilizando una función de agrupación (count) con este sub consulta: SELECT COUNT (*) A partir de dbo.LessonPlanResource lpr donde lpr.LessonPlanId = a.LessonPlanId

Sin embargo, la referencia a a.LessonPlanId es un campo no agrupado. Agrupe su consulta y puede hacer referencia a ese campo.

Pruebe esto:

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

Gracias, ¿esto sugiere que ya no necesito hacer lo distinto en la consulta interna de la cláusula from donde espero dúplex? – James

+0

No, no sería necesario, ya que cualquier agrupación sería eliminada. – kniemczak

0
  • Extracción del contar desde su selecto exterior.
  • El uso de recuento diferente en su interior selecto

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

Esto no parece funcionar. – James

Cuestiones relacionadas