SELECCIONAR múltiples columnas a través de una subconsulta


18

Estoy tratando de SELECCIONAR 2 columnas de la subconsulta en la siguiente consulta, pero no puedo hacerlo. Intenté crear una tabla de alias, pero aún no pude conseguirlos.

SELECT
  DISTINCT petid,
  userid,
  (SELECT MAX(comDate) FROM comments WHERE petid=pet.id) AS lastComDate,
  (SELECT userid FROM comments WHERE petid=pet.id ORDER BY id DESC LIMIT 1) AS lastPosterID
FROM 
  pet LEFT JOIN comments ON pet.id = comments.petid
WHERE 
  userid='ABC'      AND 
  deviceID!='ABC'   AND 
  comDate>=DATE_SUB(CURRENT_TIMESTAMP, INTERVAL 2 MONTH);

Básicamente, estoy tratando de obtener el lastComDate& lastPosterIDde la misma fila, la fila que es la última en comentarios para la mascota específica. Sugiera cómo puedo obtenerlos de manera eficiente.

La consulta anterior funciona, pero parece exagerada ya que la misma fila se obtiene dos veces. Además, la ORDER BYcláusula es significativamente más lenta que la función agregada, como encontré al realizar una consulta de perfil. Por lo tanto, se agradecería una solución que evite la clasificación.


1
Si tuviera un índice (petid, id) en la tabla de comentarios, el orden por probablemente no sería lento, pero lo primero es lo primero: parece que su consulta está preguntando por todas las mascotas donde el usuario 'ABC' ha comentado en los últimos dos meses, donde deviceID no es 'ABC' (aunque no está claro en qué tabla ID de dispositivo es una columna, posiblemente mascotas y posiblemente comentarios) y quién fue el último comentarista y la fecha de último comentario. ¿Está bien?
Michael - sqlbot

@ Michael-sqlbot - Sí, eso es exactamente lo que estoy tratando de reunir. El deviceIDes de la petstabla, lo que significa que simplemente no me consiguen las mascotas que envía el propio 'ABC'.
BufferStack

Respuestas:


13
SELECT DISTINCT petid, userid, lastComDate, lastPosterId
FROM 
    pet 
    LEFT JOIN comments ON pet.id = comments.petid 
    LEFT JOIN (
        SELECT MAX(comDate), userid, petid FROM comments GROUP BY userid
    ) a ON a.petid = pet.id
WHERE 
    userid='ABC' 
    AND deviceID!='ABC' 
    AND comDate>=DATE_SUB(CURRENT_TIMESTAMP, INTERVAL 2 MONTH)
;

También puede llevar su subconsulta a una tabla temporal si el rendimiento se ve afectado en algún momento.


También había intentado esto antes ... esto regresa NULLpara ambos lastComDatey lastPosterIdpara todos los registros.
BufferStack

¿Tiene alguna muestra de datos disponibles?
Valkyrie

¿Cómo proporciono los datos de muestra?
BufferStack

Pruebe las sugerencias en esta publicación: meta.stackexchange.com/questions/156729/…
Valkyrie

1
Eso es bueno, pero SQLFiddle es mejor;). Vea un ejemplo aquí . Es mucho mejor simplemente ver el código y los datos iniciales, no alguna tabla que necesitará formatear.
Marian

6

Dado que sus tablas se ven así:

create table pet (id int, userid int, deviceid int);
create table comments (id int, petid int, comdate date);

Esta consulta debería hacer el truco:

SELECT 
        p.id, 
        p.userid,
        (SELECT MAX(comDate)
         FROM comments
         WHERE petid = p.id
         AND comDate >= DATE_SUB(
                 CURRENT_TIMESTAMP, INTERVAL 2 MONTH)
               ) AS lastComDate,
        (SELECT userid
         FROM comments
         WHERE petid = p.id
         AND comDate >= DATE_SUB(
              CURRENT_TIMESTAMP, INTERVAL 2 MONTH
         ) ORDER BY id DESC LIMIT 1) AS lastPosterID
    FROM 
        pet p

    WHERE 
        p.userid=1
        AND p.deviceID!=1
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.