Как объединить несвязанные таблицы, но сортировать по общему типу столбца? - PullRequest
2 голосов
/ 02 декабря 2010

Хорошо, для примера у меня есть три таблицы:

**Table A**
id (serial)
timestamp (timestamp)
value1 (double)
value2 (double)

**Table B**
id (serial)
timestamp (timestamp)
text1 (text)
char1 (character)

**Table C**
id (serial)
timestamp (timestamp)
int1 (int)
int2 (int)

Поля идентификатора уникальны для каждой таблицы и действуют как первичные ключи. Метки времени вводятся, когда строки помещаются в таблицу, но не связаны с другими таблицами, и каждая таблица может иметь строки, вставляемые в разное время.

То, что я хочу, - это представление или отдельный набор данных, который содержит все записи из каждой таблицы, отсортированные по метке времени.

В этом примере это будет означать, что набор данных будет иметь следующие столбцы:

**Output Table**
timestamp (timestamp)
value1 (double)
value2 (double)
text1 (text)
char1 (character)
int1 (int)
int2 (int)

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

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

Мне просто нужно создать таблицу, состоящую из всех столбцов трех таблиц, используя одну (временную метку) в качестве общего столбца сортировки.

Что было бы лучшим способом добиться этого? Возможно ли это даже в SQL?

Моей первоначальной идеей было извлечь данные из каждой таблицы отдельно в массив (PHP / C ++), а затем выполнить там сортировку, но это кажется невероятно медленным, поэтому я надеялся на гораздо более быстрое решение SQL. 1019 *

Примечание. В каждой таблице может быть много тысяч записей. Моя база данных находится в PostgreSQL, если она уместна.

Ответы [ 4 ]

2 голосов
/ 02 декабря 2010

Следующий код делает то, что вам нужно, а также заботится о различных сопоставлениях между столбцами.Решение зависит от MySQL (из-за используемой функции CAST и проблем с сопоставлением).

SELECT * FROM (
SELECT
    `timestamp`,
    CAST(`value1` AS CHAR) AS `value1`,
    CAST(`value2` AS CHAR) AS `value2`,
    CAST(NULL AS CHAR) AS `text1`,
    CAST(NULL AS CHAR) AS `char1`,
    CAST(NULL AS SIGNED) AS `int1`,
    CAST(NULL AS SIGNED) AS `int2`
FROM `table_a`
UNION
SELECT
    `timestamp`,
    CAST(NULL AS CHAR) AS `value1`,
    CAST(NULL AS CHAR) AS `value2`,
    CAST(`text1` AS CHAR) AS `text1`,
    CAST(`char1` AS CHAR) AS `char1`,
    CAST(NULL AS SIGNED) AS `int1`,
    CAST(NULL AS SIGNED) AS `int2`
FROM `table_b`
UNION
SELECT
    `timestamp`,
    CAST(NULL AS CHAR) AS `value1`,
    CAST(NULL AS CHAR) AS `value2`,
    CAST(NULL AS CHAR) AS `text1`,
    CAST(NULL AS CHAR) AS `char1`,
    CAST(`int1` AS SIGNED) AS `int1`,
    CAST(`int2` AS SIGNED) AS `int2`
FROM `table_c`) `table_all`
ORDER BY `timestamp`

Кроме того, тот факт, что вы можете сделать это , не означаетВы должны сделать это.Лучше постарайтесь перераспределить, (де) нормализовать ваши данные, иначе вы можете столкнуться с подобными проблемами снова и снова.Сортировка множества строк в результирующем наборе UNION не эффективна ...

2 голосов
/ 02 декабря 2010

Вы можете добавить отсутствующие столбцы вручную с помощью объединения:

SELECT * FROM(
    SELECT timestamp, value1, value2, null as text1, null as char1, null as int1, null as int2 FROM tableA
    union all
    SELECT timestamp, null, null, text1, char1, null, null FROM tableB
    union all
    SELECT timestamp, null, null, null, null, int1, int2 FROM tableC
) ORDER BY timestamp;
1 голос
/ 02 декабря 2010

Используйте объединение, но добавьте дополнительные столбцы, чтобы каждая составная таблица имела одинаковую подпись .

Select id, timestamp, value1, value2, 
   Cast(null as text) text1,
   Cast(null as char(1)) char1,
   Cast(null as int) int1,
   Cast(null as int) int2 From Table1
 Union
Select id, timestamp, 
   Cast(null as double) value1, 
   Cast(null as double) value2, 
   text1, car1,
   Cast(null as int) int1,
   Cast(null as int) int2 From Table2
 Union
Select id, timestamp, 
   Cast(null as double) value1, 
   Cast(null as double) value2, 
   Cast(null as text) text1,
   Cast(null as char(1)) char1,
   int1, int2 From Table3
Order By Timestamp   
0 голосов
/ 02 декабря 2010

Полное внешнее объединение на временной метке будет работать так же, как примеры union.Не знаю о производительности, но запрос короче.

select
  coalesce(a.timestamp, b.timestamp. c.timestamp) timestamp,
  .. fields here ..
from
  tablea a
  full outer join tableb b on a.timestamp = b.timestamp
  full outer join tablec c on c.timestamp = a.timestamp
order by
  1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...