Как сделать «горизонтальный UNION» в MySQL?(счетные столы) - PullRequest
5 голосов
/ 29 марта 2011

Я ищу возможность объединить или объединить две (или более) таблицы. Я не могу ПРИСОЕДИНИТЬСЯ ко всем таблицам, так как нет ссылок и нет соответствующих столбцов. Если я присоединяюсь без какого-либо «ВКЛ», я получу все данные из Таблицы 1, умноженные на все данные из Таблицы 2 (не то, что я хочу). Поэтому я попытался предоставить поддельные rownums с пользовательскими переменными MySQL, но, поскольку во всех таблицах есть разные объемы данных, я не могу их сравнить. Это немного сложно объяснить. Поэтому я приведу несколько примеров.

Пример 1 (Таблица 1 = 4 строки, Таблица 2 = 3 строки, Результат = 4 строки)

+---------+---------+---------------+
| Table 1 | Table 2 | Result        |
+---------+---------+-------+-------+
| Col 1   | Col 1   | Col 1 | Col 2 |
+---------+---------+-------+-------+
| A       | H       | A     | H     |
| B       | I       | B     | I     |
| C       | J       | C     | J     |
| D       |         | D     | NULL  |
+---------+---------+-------+-------+

Пример 2 (Таблица 1 = 3 строки, Таблица 2 = 4 строки, Результат = 4 строки)

+---------+---------+---------------+
| Table 1 | Table 2 | Result        |
+---------+---------+-------+-------+
| Col 1   | Col 1   | Col 1 | Col 2 |
+---------+---------+-------+-------+
| A       | H       | A     | H     |
| B       | I       | B     | I     |
| C       | J       | C     | J     |
|         | K       | NULL  | K     |
+---------+---------+-------+-------+

Пример 3 (Таблица 1 = 3 строки, Таблица 2 = 4 строки, Таблица 3 = 2 строки, Результат = 4 строки)

+---------+---------+---------+-----------------------+
| Table 1 | Table 2 | Table 3 | Result                |
+---------+---------+---------+-------+-------+-------+
| Col 1   | Col 1   | Col 1   | Col 1 | Col 2 | Col 3 |
+---------+---------+---------+-------+-------+-------+
| A       | H       | O       | A     | H     | O     |
| B       | I       | P       | B     | I     | P     |
| C       | J       |         | C     | J     | NULL  |
|         | K       |         | NULL  | K     | NULL  |
+---------+---------+---------+-------+-------+-------+

Теперь по-настоящему сложная часть. Мне нужно это как запрос. Я не хочу заполнять другие временные таблицы. Если возможно: -)

Ответы [ 2 ]

5 голосов
/ 29 марта 2011

Я полагаю, что вы присоединяетесь к плотному порядковому рангу каждой таблицы, просто упорядоченной по значению "Col 1"?

Это фактически полное внешнее соединение по рангу каждой таблицы.

К сожалению, MySQL не поддерживает аналитическую функцию ROW_NUMBER (), которая сделала бы это относительно простым:

SELECT *
FROM (SELECT "Col 1", ROW_NUMBER() (OVER ORDER BY "Col 1") AS RowNum FROM "Table 1") AS T1
FULL OUTER JOIN (SELECT "Col 1", ROW_NUMBER() (OVER ORDER BY "Col 1") AS RowNum FROM "Table 2") AS T2
    ON T2.RowNum = T1.RowNum
FULL OUTER JOIN (SELECT "Col 1", ROW_NUMBER() (OVER ORDER BY "Col 1") AS RowNum FROM "Table 3") AS T3
    ON T3.RowNum = T2.RowNum
ORDER BY COALESCE(T1.RowNum, T2.RowNum, T3.RowNum)

В MySQL есть альтернативы, но я не знаком с обходными путями.

Что касается обходного пути ПОЛНОГО ВНЕШНЕГО СОЕДИНЕНИЯ, для рангов это легко, поскольку известные ранги - это просто натуральные числа:

SELECT *
FROM Numbers
LEFT JOIN (SELECT "Col 1", ROW_NUMBER() (OVER ORDER BY "Col 1") AS RowNum FROM "Table 1") AS T1
    ON T1.RowNum = Numbers.Number
LEFT JOIN (SELECT "Col 1", ROW_NUMBER() (OVER ORDER BY "Col 1") AS RowNum FROM "Table 2") AS T2
    ON T2.RowNum = Numbers.Number
LEFT JOIN (SELECT "Col 1", ROW_NUMBER() (OVER ORDER BY "Col 1") AS RowNum FROM "Table 3") AS T3
    ON T2.RowNum = Numbers.Number
WHERE COALESCE(T1.RowNum, T2.RowNum, T3.RowNum) IS NOT NULL
ORDER BY Numbers.Number
0 голосов
/ 29 марта 2011

Это сложный метод с использованием подготовленных запросов:

SET @r1= (SELECT COUNT(*) FROM table1);
SET @r2= (SELECT COUNT(*) FROM table2);
SET @a=-1;

SET @query= IF (@r1 > @r2, 
    (
        SELECT GROUP_CONCAT(CONCAT(
        'SELECT (SELECT col1 FROM table1 LIMIT ', @a:=@a+1, ', 1) AS col1,
        (SELECT col1 FROM table2 LIMIT ', @a, ', 1) AS col2 FROM table1')
        SEPARATOR ' union ') FROM table1
    ),
    (
        SELECT GROUP_CONCAT(CONCAT(
        'SELECT (select col1 from table1 limit ', @a:=@a+1,', 1) as col1,
        (SELECT col1 FROM table2 LIMIT ', @a, ', 1) AS col2 FROM table2')
        SEPARATOR ' union ') FROM table2
    )
);
PREPARE my_query FROM @query;
EXECUTE my_query;

Имейте в виду, что это вообще не эффективный метод, он просто решает вашу проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...