sql >> Base de Datos >  >> RDS >> PostgreSQL

¿Mejor manera que múltiples declaraciones SELECT?

Puede agrupar la mayor parte del costo en una sola consulta principal en un CTE y reutilice el resultado varias veces.
Esto devuelve una fila única con tres columnas nombrado después de cada type (según lo solicitado en el comentario ):

WITH cte AS (
   SELECT cai.id, cai.activity_id, cas.key, cas.value
   FROM   common_activityinstance cai
   JOIN   common_activityinstance_settings s ON s.activityinstance_id = cai.id
   JOIN   common_activitysetting cas ON cas.id = s.id
   WHERE  cai.end_time::date = '2015-09-12'   -- problem?
   AND    cai.activity_type = 'QZ'
   AND   (cas.key = 'disable_student_nav' AND cas.value IN ('True', 'False') OR
          cas.key = 'pacing' AND cas.value IN ('student', 'teacher'))
   )
SELECT *
FROM  (
   SELECT count(*) AS spf
   FROM  (
      SELECT c.id
      FROM   cte c
      JOIN   quizzes_quiz q ON q.id = c.activity_id
      WHERE  q.name <> 'Exit Ticket Quiz'
      AND   (c.key, c.value) IN (('disable_student_nav', 'True')
                               , ('pacing', 'student'))
      GROUP  BY 1
      HAVING count(*) = 2
      ) sub
   ) spf
,  (
   SELECT count(key = 'disable_student_nav' AND value = 'False' OR NULL) AS spn
        , count(key = 'pacing' AND value = 'teacher' OR NULL) AS tp
   FROM   cte
   ) spn_tp;

Debería funcionar para Postgres 9.3. En Postgres 9.4 puede usar el nuevo agregado FILTER cláusula:

  count(*) FILTER (WHERE key = 'disable_student_nav' AND value = 'False') AS spn
, count(*) FILTER (WHERE key = 'pacing' AND value = 'teacher') AS tp

Detalles para ambas variantes de sintaxis:

La condición marcada como problem? puede ser un gran problema de rendimiento, según el tipo de datos de cai.end_time . Por un lado, no es sargable . Y si es un timestamptz tipo, la expresión es difícil de indexar, porque el resultado depende de la configuración de la zona horaria actual de la sesión, lo que también puede generar resultados diferentes cuando se ejecuta en diferentes zonas horarias.

Comparar:

Solo tiene que nombrar la zona horaria que se supone que define su fecha. Tomando mi zona horaria en Viena como ejemplo:

WHERE  cai.end_time >= '2015-09-12 0:0'::timestamp AT TIME ZONE 'Europe/Vienna' 
AND    cai.end_time <  '2015-09-13 0:0'::timestamp AT TIME ZONE 'Europe/Vienna'

Puede proporcionar timestamptz simple valores también. Incluso podrías simplemente:

WHERE  cai.end_time >= '2015-09-12'::date
AND    cai.end_time <  '2015-09-12'::date + 1

Pero la primera variante no depende de la configuración de la zona horaria actual.
Explicación detallada en los enlaces de arriba.

Ahora la consulta puede usar su índice y debería ser mucho más rápida si hay muchos días diferentes en su tabla.