将一个查询的结果输入另一个查询

时间:2012-03-09 22:04:19

标签: mysql sql database

我试图将我的问题简化为我在下面写下的一个基本示例,实际问题要复杂得多,因此下面的查询可能没什么意义,但基本概念是相同的(从一个查询到另一个查询的数据) )。

查询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 |
+--------+--------+

//从下面我需要通过上面的PingID替换11,然后通过BaseID替换10,然后将结果显示为上面的第三列(如果没有结果则为0,如果结果则为1)

查询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;

我该怎么做?我不知道我会收到什么样的建议,但请理解,查询2实际上超过200行,我基本上无法触摸它,所以我没有那么多的灵活性,因为我喜欢和理想情况下我想在SQL中使用它,而不必编写脚本。

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 个答案:

答案 0 :(得分:4)

处理此问题的最简单方法是临时表,描述为herehere。如果您创建一个空表来存储结果(让我们称之为tbl_temp1),您可以这样做:

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

然后你可以随意查询:

SELECT PingID, BaseID from tbl_temp1 ...

已编辑添加:

来自CREATE TEMPORARY TABLE的文档:

  

创建表时可以使用TEMPORARY关键字。临时的   table仅对当前连接可见,并被删除   连接关闭时自动这意味着两个   不同的连接可以使用相同的临时表名   相互冲突或与现有的非TEMPORARY表冲突   同名。 (现有表隐藏到临时表之前   被丢弃了。)

答案 1 :(得分:4)

如果这是一个更扁平的查询,那么就会有一个直截了当的答案。

当然可以使用派生表作为外部查询的输入。一个简单的例子是:

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

在内联查询中使用派生表greetings。 (这个简单示例的SQL小提琴:http://sqlfiddle.com/#!3/49425/2

遵循这个逻辑会让我们假设您可以将第一个查询转换为query1的派生表,然后将query2重新转换为select语句。

为此,我构建了以下内容:

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;

我已将query2插入query1的select子句,并插入query1.pingIdquery1.baseId代替1110,分别。如果保留11和10,则此查询有效(但显然只为每行生成相同的数据)。

但是当执行此操作时,我会收到错误:Unknown column 'query1.pingId'。显然,在嵌套派生表中无法看到query1。

一般来说,这种类型的查询是可能的,当嵌套只有1级深度时(根据我在顶部的问候示例),必须有逻辑限制,为什么这种嵌套级别是不可能的。 (抽出数据库理论书的时间......)

如果我遇到这个问题,我会重写并压缩查询以获取我想要的真实数据。并消除一些事情,包括在query1中使用的非常讨厌group by以获取给定pingId的最大baseId。

你说由于外部限制,这是不可能的。所以,这最终是一个非答案的答案。不是很有用,但也许它值得一试。

(SQL Fiddle for all this:http://sqlfiddle.com/#!2/bac74/35

答案 2 :(得分:1)

如果您无法修改查询2,那么我们无法建议。以下是两个查询的组合,嵌套级别降低。我怀疑使用大型数据集会很慢 -

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;