alimentar el resultado de una consulta a otra
Frecuentes
Visto 5,607 veces
4
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);
3 Respuestas
5
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
4
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
1
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 mysql sql database or haz tu propia pregunta.
SQL Fiddle para lo anterior: sqlfiddle.com/#!2/c6781/1 - Mike Ryan
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 - user391986
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. - Mike Ryan