I tried to simplify my question to a basic example I wrote down below, the actual problem is much more complex so the below queries might not make much sense but the basic concepts are the same (data from one query as argument to another).
Query 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 |
+--------+--------+
// from below I need to replace 11 by PingID above and 10 by BaseID above then the results to show up on as third column above (0 if no results, 1 if results)
Query 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;
How can I do this? Again I'm not sure what kind of advice I will receive but please understand that the Query 2 is in reality over 200 lines and I basically can't touch it so I don't have so much flexibility as I'd like and ideally I'd like to get this working all in SQL without having to script this.
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);
If this were a more flattened query, then there would a straightforward answer.
It is certainly possible to use a derived table as the input to outer queries. A simple example would be:
select
data1,
(select data3 from howdy1 where howdy1.data1 = greetings.data1) data3_derived
from
(select data1 from hello1 where hello1.data2 < 4) as greetings;
where the derived table greetings
is used in the inline query. (SQL Fiddle for this simplistic example: http://sqlfiddle.com/#!3/49425/2 )
Following this logic would lead us to assume that you could cast your first query as a derived table of query1
and then recast query2
into the select statement.
For that I constructed the following:
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;
where I have inserted query2
into a select clause from query1
and inserted query1.pingId
and query1.baseId
in place of 11
and 10
, respectively. If 11 and 10 are left in place, this query works (but obviously only generates the same data for each row).
But when this is executed, I'm given an error: Unknown column 'query1.pingId'
. Obviously, query1 cannot be seen inside the nested derived tables.
Since, in general, this type of query is possible, when the nesting is only 1 level deep (as per my greeting example at the top), there must be logical restrictions as to why this level of nesting isn't possible. (Time to pull out the database theory book...)
If I were faced with this, I'd rewrite and flatten the queries to get the real data that I wanted. And eliminate a couple things including that really nasty group by
that is used in query1 to get the max baseId for a given pingId.
You say that's not possible, due to external constraints. So, this is, ultimately, a non-answer answer. Not very useful, but maybe it'll be worth something.
(SQL Fiddle for all this: http://sqlfiddle.com/#!2/bac74/35 )
The simplest way of dealing with this is temporary tables, described here and here. If you create an empty table to store your results (let's call it tbl_temp1
) you can to this:
INSERT INTO tbl_temp1 (PingID, BaseID)
SELECT Ping.ID as PingID, Base.ID as BaseID
FROM ...
Then you can query it however you like:
SELECT PingID, BaseID from tbl_temp1 ...
Edited to add:
From the docs for CREATE TEMPORARY TABLE:
You can use the TEMPORARY keyword when creating a table. A TEMPORARY table is visible only to the current connection, and is dropped automatically when the connection is closed. This means that two different connections can use the same temporary table name without conflicting with each other or with an existing non-TEMPORARY table of the same name. (The existing table is hidden until the temporary table is dropped.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With