alimentar el resultado de una consulta a otra

Traté de simplificar mi pregunta a un ejemplo básico que escribí a continuación, el problema real es mucho más complejo, por lo que las consultas a continuación pueden no tener mucho sentido, pero los conceptos básicos son los mismos (datos de una consulta como argumento a otro).

Consulta 1:

SELECT Ping.ID as PingID, Base.ID as BaseID FROM 
    (SELECT l.ID, mg.DateTime from list l
     JOIN mygroup mg ON mg.ID = l.MyGroup
     WHERE l.Type = "ping"
     ORDER BY l.ID DESC
    ) Ping
    INNER JOIN
    (SELECT l.ID, mg.DateTime from list l
     JOIN mygroup mg ON mg.ID = l.MyGroup
     WHERE l.Type = "Base"
     ORDER BY l.ID DESC
    ) Base
    ON Base.DateTime < Ping.DateTime
    GROUP BY Ping.ID
    ORDER BY Ping.ID DESC;

+--------+--------+
| PingID | BaseID |
+--------+--------+
|     11 |     10 |
|      9 |      8 |
|      7 |      6 |
|      5 |      3 |
|      4 |      3 |
+--------+--------+

// desde abajo, necesito reemplazar 11 por PingID arriba y 10 por BaseID arriba, luego los resultados aparecerán en la tercera columna arriba (0 si no hay resultados, 1 si hay resultados)

Consulta 2:

SELECT * FROM 
    (SELECT sl.Data FROM list l 
     JOIN sublist sl ON sl.ParentID = l.ID
    WHERE l.Type = "ping" AND l.ID = 11) Ping
    INNER JOIN
    (SELECT sl.Data FROM list l 
     JOIN sublist sl ON sl.ParentID = l.ID
    WHERE l.Type = "base" AND l.ID = 10) Base
    ON Base.Data < Ping.Data;

¿Cómo puedo hacer esto? Nuevamente, no estoy seguro de qué tipo de consejo recibiré, pero comprenda que la Consulta 2 tiene en realidad más de 200 líneas y básicamente no puedo tocarla, por lo que no tengo tanta flexibilidad como me gustaría e idealmente Me gustaría que esto funcione todo en SQL sin tener que escribir esto.

CREATE DATABASE lookback;
use lookback;

CREATE TABLE mygroup (
ID                          BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, 
DateTime                    DateTime    
) ENGINE=InnoDB;

CREATE TABLE list (
ID                          BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Type                        VARCHAR(255),
MyGroup                     BIGINT NOT NULL,
Data                        INT NOT NULL
) ENGINE=InnoDB;

CREATE TABLE sublist (
ID                          BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
ParentID                    BIGINT NOT NULL,
Data                        INT NOT NULL
) ENGINE=InnoDB;

INSERT INTO mygroup (DateTime) VALUES ("2012-03-09 22:33:19"), ("2012-03-09 22:34:19"), ("2012-03-09 22:35:19"), ("2012-03-09 22:36:19"), ("2012-03-09 22:37:19"), ("2012-03-09 22:38:19"), ("2012-03-09 22:39:19"), ("2012-03-09 22:40:19"), ("2012-03-09 22:41:19"), ("2012-03-09 22:42:19"), ("2012-03-09 22:43:19");    
INSERT INTO list (Type, MyGroup, Data) VALUES ("ping", 1, 4), ("base", 2, 2), ("base", 3, 4), ("ping", 4, 7), ("ping", 5, 8), ("base", 6, 7), ("ping", 7, 8), ("base", 8, 3), ("ping", 9, 10), ("base", 10, 2), ("ping", 11, 3);
INSERT INTO sublist (ParentID, Data) VALUES (1, 2), (2, 3), (3, 6), (4, 8), (5, 4), (6, 5), (7, 1), (8, 9), (9, 11), (10, 4), (11, 6);

preguntado el 09 de marzo de 12 a las 22:03

SQL Fiddle para lo anterior: sqlfiddle.com/#!2/c6781/1 -

Gracias a todos, aprendí un montón de cosas con las respuestas, desafortunadamente ninguna estaba completa para hacer que esto funcionara, así que después de jugar un poco más, ¡encontré una solución que funciona! Básicamente, creé un procedimiento almacenado para la Consulta 2 y luego, desde la consulta 1, agregué un argumento adicional en SELECCIONAR que lo llama SELECCIONAR Ping.ID como PingID, Base.ID como BaseID, (SELECT fnc_callquerytwo(PingID, BaseID)) DESDE -

Si query2 no se puede cambiar, probablemente sea lo mejor. Probé una tabla temporal, alimentándola de la misma manera que alimenté query1 en mi respuesta y todavía recibí el error de columna desconocido. -

3 Respuestas

La forma más sencilla de tratar con esto son las tablas temporales, descritas aquí y aquí. Si crea una tabla vacía para almacenar sus resultados (llamémoslo tbl_temp1) puedes hacer esto:

INSERT INTO tbl_temp1 (PingID, BaseID)
SELECT Ping.ID as PingID, Base.ID as BaseID 
FROM ...

Luego puedes consultarlo como quieras:

SELECT PingID, BaseID from tbl_temp1 ...

Editado para agregar:

De los documentos para CREAR TABLA TEMPORAL:

Puede utilizar la palabra clave TEMPORARY al crear una tabla. Una tabla TEMPORAL solo es visible para la conexión actual y se elimina automáticamente cuando se cierra la conexión. Esto significa que dos conexiones diferentes pueden usar el mismo nombre de tabla temporal sin entrar en conflicto entre sí o con una tabla no TEMPORAL existente del mismo nombre. (La tabla existente está oculta hasta que se elimina la tabla temporal).

respondido 12 mar '12, 22:03

Intentando esto ahora, ¿la tabla temporal debe borrarse manualmente cada vez? ¿Existe la posibilidad de que dos ejecuciones mezclen los datos? - user391986

Si esta fuera una consulta más plana, entonces habría una respuesta directa.

Ciertamente, es posible utilizar una tabla derivada como entrada para consultas externas. Un ejemplo sencillo sería:

select 
  data1, 
  (select data3 from howdy1 where howdy1.data1 = greetings.data1) data3_derived
from 
  (select data1 from hello1 where hello1.data2 < 4) as greetings;

donde la tabla derivada greetings se utiliza en la consulta en línea. (SQL Fiddle para este ejemplo simplista: http://sqlfiddle.com/#!3/49425/2 )

Seguir esta lógica nos llevaría a suponer que podría emitir su primera consulta como una tabla derivada de query1 y luego reformular query2 en la declaración de selección.

Para eso construí lo siguiente:

select query1.pingId, query1.baseId,
       (SELECT ping.Data pingData FROM 
         (SELECT sl.Data FROM list l 
            JOIN sublist sl ON sl.ParentID = l.ID
            WHERE l.Type = "ping" AND l.ID = query1.pingId
         ) Ping
         INNER JOIN
         (SELECT sl.Data FROM list l 
            JOIN sublist sl ON sl.ParentID = l.ID
            WHERE l.Type = "base" AND l.ID = query1.baseId
         ) Base
       ON Base.Data < Ping.Data) 
 from 
   (SELECT Ping.ID as PingID, Base.ID as BaseID FROM 
        (SELECT l.ID, mg.DateTime from list l
         JOIN mygroup mg ON mg.ID = l.MyGroup
         WHERE l.Type = "ping"
         ORDER BY l.ID DESC
     ) Ping
     INNER JOIN
     (SELECT l.ID, mg.DateTime from list l
         JOIN mygroup mg ON mg.ID = l.MyGroup
         WHERE l.Type = "Base"
         ORDER BY l.ID DESC
     ) Base
     ON Base.DateTime < Ping.DateTime
     GROUP BY Ping.ID
   )  query1
   order by pingId desc;

donde he insertado query2 en una cláusula de selección de query1 e insertado query1.pingId y query1.baseId en lugar de 11 y 10, respectivamente. Si se dejan 11 y 10 en su lugar, esta consulta funciona (pero obviamente solo genera los mismos datos para cada fila).

Pero cuando esto se ejecuta, me da un error: Unknown column 'query1.pingId'. Obviamente, consulta1 no se puede ver dentro de las tablas derivadas anidadas.

Dado que, en general, este tipo de consulta es posible, cuando el anidamiento tiene solo 1 nivel de profundidad (según mi ejemplo de saludo en la parte superior), debe haber restricciones lógicas sobre por qué este nivel de anidamiento no es posible. (Hora de sacar el libro de teoría de la base de datos...)

Si me enfrentara a esto, reescribiría y aplanaría las consultas para obtener los datos reales que quería. Y elimine un par de cosas, incluida la realmente desagradable. group by que se usa en query1 para obtener el baseId máximo para un pingId dado.

Dices que eso no es posible, debido a restricciones externas. Entonces, esta es, en última instancia, una respuesta sin respuesta. No es muy útil, pero tal vez valga la pena.

(SQL Fiddle para todo esto: http://sqlfiddle.com/#!2/bac74/35 )

respondido 10 mar '12, 04:03

ah lástima que hubiera sido perfecto! - user391986

Si no puede modificar la consulta 2, entonces no hay nada que podamos sugerir. Aquí hay una combinación de sus dos consultas con un nivel reducido de anidamiento. Sospecho que esto sería lento con un gran conjunto de datos:

SELECT tmp1.PingID, tmp1.BaseID, IF(slb.Data, 1, 0) AS third_col
FROM (
  SELECT lp.ID AS PingID, MAX(lb.ID) AS BaseID
  FROM MyGroup mgp
  INNER JOIN MyGroup mgb
    ON mgb.DateTime < mgp.DateTime
  INNER JOIN list lp
    ON mgp.ID = lp.MyGroup
    AND lp.Type = 'ping'
  INNER JOIN list lb
    ON mgb.ID = lb.MyGroup
    AND lb.Type = 'base'
  GROUP BY lp.ID DESC
) AS tmp1
LEFT JOIN sublist slp
  ON tmp1.PingID = slp.ParentID
LEFT JOIN sublist slb
  ON tmp1.BaseID = slb.ParentID
  AND slb.Data < slp.Data;

respondido 10 mar '12, 17:03

Gracias nnichols, desafortunadamente la consulta 2 es demasiado compleja para manipularla, una triste realidad con la que debo lidiar. - user391986

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.