подача результата одного запроса в другой - PullRequest
2 голосов
/ 10 марта 2012

Я попытался упростить свой вопрос до базового примера, который я записал ниже, реальная проблема гораздо сложнее, поэтому приведенные ниже запросы могут не иметь особого смысла, но основные концепции одинаковы (данные из одного запроса в качестве аргумента для другого).

Запрос 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;

Как я могу это сделать?Опять же, я не уверен, какой совет я получу, но, пожалуйста, поймите, что Query 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 ]

4 голосов
/ 10 марта 2012

Если бы это был более плоский запрос, то был бы прямой ответ.

Конечно, можно использовать производную таблицу в качестве входных данных для внешних запросов.Простой пример:

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 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.pingId и query1.baseId вместо 11 и 10 соответственно.Если 11 и 10 оставить на месте, этот запрос работает (но, очевидно, генерирует одни и те же данные для каждой строки).

Но когда это выполняется, мне выдается ошибка: Unknown column 'query1.pingId'.Очевидно, что query1 нельзя увидеть внутри вложенных производных таблиц.

Так как, в общем, этот тип запроса возможен, когда вложенность имеет только 1 уровень глубины (согласно моему примеру приветствия вверху), тамдолжны быть логические ограничения относительно того, почему этот уровень вложенности невозможен.(Время вытащить книгу теории баз данных ...)

Если бы я столкнулся с этим, я бы переписал и сгладил запросы, чтобы получить реальные данные, которые я хотел.И исключите пару вещей, включая действительно неприятный group by, который используется в query1 для получения максимального baseId для данного pingId.

Вы говорите, что это невозможно из-за внешних ограничений.Итак, это, в конечном счете, ответ без ответа.Не очень полезно, но, возможно, оно чего-то стоит.

(SQL Fiddle для всего этого: http://sqlfiddle.com/#!2/bac74/35)

4 голосов
/ 10 марта 2012

Самый простой способ справиться с этим - это временные таблицы, описанные здесь и здесь .Если вы создадите пустую таблицу для хранения результатов (назовем ее tbl_temp1), вы можете сделать следующее:

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

Затем вы можете запросить ее, как вам нравится:

SELECT PingID, BaseID from tbl_temp1 ...

Отредактировано, чтобы добавить:

Из документов для СОЗДАТЬ ВРЕМЕННУЮ ТАБЛИЦУ :

При создании таблицы можно использовать ключевое слово TEMPORARY.Таблица TEMPORARY видна только текущему соединению и автоматически удаляется при закрытии соединения.Это означает, что два разных соединения могут использовать одно и то же временное имя таблицы, не конфликтуя друг с другом или с существующей, не являющейся TEMPORARY, таблицей с одним и тем же именем.(Существующая таблица скрыта, пока временная таблица не будет удалена.)

1 голос
/ 10 марта 2012

Если вы не можете изменить запрос 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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...