Как сделать объединение в SQL на основе имени таблицы? - PullRequest
0 голосов
/ 09 декабря 2008

Хорошо, у нас есть несколько таблиц с такими именами:

training_data_001
training_data_002
training_data_003
training_data_004
training_data_005

А затем, чтобы найти те, которые мы смотрим на поле в другой таблице, давайте просто назовем его master.training_type.

Во всяком случае, мне было интересно, знает ли кто-нибудь, как сделать странное имя таблицы, основанное на соединении с такого рода данными. Как то так:

SELECT foo FROM master WHERE id = ? 
INNER JOIN training_data_${master.training_type}
ON foo.id = training_data_${master.training_type}.foo_id

Я знаю, что могу сделать это на стороне клиента, но было бы неплохо, чтобы БД это сделал.

Также обратите внимание: это SQL Server.

Обновление : Я решил просто сделать это на стороне клиента. В любом случае, спасибо.

Спасибо!

-fREW

Ответы [ 5 ]

2 голосов
/ 09 декабря 2008

Вы можете использовать динамический SQL только для чтения master.training_type, чтобы построить строку, которую вы затем выполните, используя EXEC (@stringvar)

1 голос
/ 09 декабря 2008

Разделенное представление - один из возможных подходов. Поскольку вы выбираете только столбец foo, действительно ли вы просто проверяете наличие строки в таблице тренировок через INNER JOIN? Кроме того, похоже, что вы пытаетесь использовать foo в качестве псевдонима в своем соединении, но в предложении SELECT это не настроено таким образом В результате я думаю, что вы действительно хотите.

Еще один вопрос ... статичен ли набор тренировочных столов? Вы ожидаете, что сможете добавить новую таблицу с новым номером суффикса и она будет работать?

Другое возможное решение:

SELECT
     foo
FROM
     dbo.master m
WHERE
     (training_type = '001' AND EXISTS (SELECT * FROM dbo.training_data_001 WHERE foo_id = m.id)) OR
     (training_type = '002' AND EXISTS (SELECT * FROM dbo.training_data_002 WHERE foo_id = m.id)) OR
     (training_type = '003' AND EXISTS (SELECT * FROM dbo.training_data_003 WHERE foo_id = m.id)) OR
     (training_type = '004' AND EXISTS (SELECT * FROM dbo.training_data_004 WHERE foo_id = m.id)) OR
     (training_type = '005' AND EXISTS (SELECT * FROM dbo.training_data_005 WHERE foo_id = m.id))

Если вы действительно хотите вернуть столбцы из таблиц обучающих данных, вы можете использовать что-то вроде:

SELECT
     m.id,
     COALESCE(t1.my_col, t2.my_col, t3.my_col, t4.my_col, t5.my_col) AS my_col
FROM
     dbo.master m
LEFT OUTER JOIN dbo.training_data_001 t1 ON m.training_type = '001' AND t1.foo_id = m.id
LEFT OUTER JOIN dbo.training_data_002 t1 ON m.training_type = '002' AND t2.foo_id = m.id
LEFT OUTER JOIN dbo.training_data_003 t1 ON m.training_type = '003' AND t3.foo_id = m.id
LEFT OUTER JOIN dbo.training_data_004 t1 ON m.training_type = '004' AND t4.foo_id = m.id
LEFT OUTER JOIN dbo.training_data_005 t1 ON m.training_type = '005' AND t5.foo_id = m.id
1 голос
/ 09 декабря 2008

сделать что-то вроде этого:

create view training_data_all as
select '001' as training_type, * from training_data_001
union all
select '002' as training_type, * from training_data_002
union all
select '003' as training_type, * from training_data_003
union all
select '004' as training_type, * from training_data_004
union all
select '005' as training_type, * from training_data_005

, затем просто выберите и присоединитесь к нему:

SELECT foo FROM master WHERE id = ? 
INNER JOIN training_data_all
ON foo.id = training_data_all.foo_id
WHERE training_data_all.training_type = ${master.training_type}

Если список таблиц будет со временем увеличиваться / уменьшаться, вы можете динамически записывать это же представление на основе существующих таблиц, выполняя некоторые операции поиска в системных таблицах.

Ничего из этого не очень эффективно, хотя. Можете ли вы просто вытолкнуть эти данные в объединенную таблицу через некоторый фиксированный интервал?

1 голос
/ 09 декабря 2008

Если все таблицы имеют одинаковую структуру, создайте Секционированное представление для всех таблиц и объединитесь с представлением. Необходимо создать проверочное ограничение для столбца (возможно, для даты), чтобы оптимизатор запросов мог выполнить удаление разделов.

1 голос
/ 09 декабря 2008

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

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