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

4

我会尽力为您进行翻译,以下是需要翻译的内容:

我试图通过下面写的基本示例来简化我的问题,实际问题要复杂得多,因此下面的查询可能没有太多意义,但基本概念是相同的(从一个查询中获取数据作为另一个查询的参数)。

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

// 我需要将下面的11替换为上面的PingID,将10替换为上面的BaseID,然后将结果显示在第三列上方(如果没有结果,则为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);

2
以上的 SQL Fiddle:http://sqlfiddle.com/#!2/c6781/1 - Mike Ryan
谢谢大家,通过这些答案我学到了很多东西。不幸的是,没有一个完整的答案可以让它正常工作,所以在再次尝试一番后,我终于找到了一个可行的解决方案!我基本上为查询2创建了一个存储过程,然后在查询1中,我只是添加了一个额外的参数在SELECT语句中调用它:SELECT Ping.ID as PingID, Base.ID as BaseID, (SELECT fnc_callquerytwo(PingID, BaseID)) FROM - user391986
如果query2是不可更改的,那可能是最好的。我曾尝试使用临时表,以与我将query1输入到我的答案中的方式相同进行输入,但仍然出现了未知列错误。 - Mike Ryan
3个回答

5

处理这个问题最简单的方法是使用临时表,可以在这里这里找到相关信息。如果你创建一个空表来存储结果(我们称之为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关键字。TEMPORARY表仅对当前连接可见,并在关闭连接时自动删除。这意味着两个不同的连接可以使用相同的临时表名称而不会相互冲突,也不会与同名的现有非TEMPORARY表发生冲突。(现有表将被隐藏,直到临时表被删除。)


现在正在尝试,临时表每次需要手动清除吗?有可能两次运行会混淆数据吗? - user391986

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 Fiddle: 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中选择的子句中,并用query1.pingIdquery1.baseId替换了1110。如果保留11和10,此查询将起作用(但显然只为每行生成相同的数据)。
但是当执行此操作时,会出现错误:Unknown column 'query1.pingId'。显然,在嵌套的派生表内部无法看到query1。
由于通常情况下,仅在嵌套深度为1级时才可能进行此类查询(如我在顶部的示例中所示),因此必须存在逻辑限制,以防止这种嵌套深度。 (是时候拿出数据库理论书了...)
如果我面临这个问题,我会重写并展开查询,以获取我想要的真实数据。并消除其中一些内容,包括在query1中使用的非常恶心的group by,以获取给定pingId的最大baseId。
你说由于外部限制这是不可能的。因此,这最终是一个没有答案的答案。不是很有用,但也许它会有些价值。
(所有这些的SQL Fiddle: http://sqlfiddle.com/#!2/bac74/35

啊,太糟糕了,那本来会是完美的! - user391986

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;

谢谢nnichols,不幸的是,查询2太复杂了,我必须面对这个悲伤的现实。 - user391986

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接