2016-01-12 7 views
0

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

С точки зрения соединений, идентификаторы уникальны по всей базе данных, поэтому два идентификатора не будут перекрываться. Однако я не знаю, какая подтаблица имеет идентификатор. Я могу найти это, потянув в несвязанную таблицу, которая имеет информацию (назовите ее Таблицей объектов). Один из столбцов даст мне имя таблицы для информации (в моем примере ниже, Person). Ниже я привел простой пример. Можете ли вы увидеть, как я мог бы выполнить это в одном запросе? Что-то вроде этого, к чему я стремлюсь, но я начинаю думать, что это невозможно.

SELECT * FROM base_table 
LEFT JOIN object ON object.id = base_table.role 
LEFT JOIN [object.type] tmp ON tmp.entity_id = base_table.entity_id 

id | role | entity_id  (Base Table) 
--------------------- 
1 | 101 | 1000 


id | type     (Objects Table) 
------------ 
101| person 

entity_id | name | etc.. (Person Table) 
------------------------ 
1000  | Bob | ... 

Я также ожидаю объединения может быть возможным решением - но другой тогда просто подключить все возможные таблицы и разбор столбцов, чтобы соответствовать должным образом (что это может быть целых 20 столов), я предпочел бы не , Это решение также немного похоже на то, что столбцы не всегда соответствуют хорошему (например, таблица Person не имеет аналогичных столбцов в таблице адресов)

+0

какой будет прецедент для этого? – JamieD77

+0

Есть ли фиксированное количество значений для столбца [object.type], или число возможных значений будет расти в будущем? –

+0

Чтобы ответить в порядке - пример использования предназначен для отображения списка информации, относящейся к базовой таблице. Например. У меня есть таблица для людей и таблица для объектов, где человек может быть связан со многими объектами. В настоящее время это фиксированное число, но может измениться в будущем (это не регулярное изменение). – Sh4d0wsPlyr

ответ

2

Я не думаю, что идея объединения влево - это плохо, если вы просто игнорируете тип объекта.

Поскольку каждый идентификатор уникален, вам не нужно вообще смотреть на тип, если вы используете coalesce. Таким образом, чтобы использовать @TT модель в качестве примера:

SELECT bt.*, 
    COALESCE(P.f1, L.f1, C.f1) AS f1, 
    -- ..., 
    COALESCE(P.fn, L.fn, C.fn) AS fn 
FROM 
    base_table AS bt 
    LEFT JOIN Person AS P ON P.entity_id = bt.entity_id 
    LEFT JOIN [Legal Person] AS L ON L.entity_id = bt.entity_id 
    LEFT JOIN Counterpart AS C ON C.entity_id = bt.entity_id 

В зависимости от объема данных и индексов это может работать быстрее или так же, как, например ТТ - помните, что есть только один выбор с N включается в то время как TT имеет N выбирает , 2N соединяется. Это зависит от ваших данных.

Если есть какое-либо поле (fz), которое не отображается во всех типах, то вы просто не подчеркиваете это в предложении coalesce.

Я думаю, что этот стиль может быть проще поддерживать и понимать и будет таким же или быстрее, чем TT-код.

+0

В вашем сравнении вы не говорите, что 1) запросы в конструкции UNION ALL будут выполняться в [parallel] (https://stackoverflow.com/questions/11571036/unioning-in-parallel-will-sql-server -сделай это); 2) мощности различны; каждый запрос в UNION ALL конструирует JOINs за меньшее количество строк, чем большой запрос, который связывается с каждой строкой. 3), что дополнительное соединение в каждом запросе в UNION ALL не обязательно должно быть с двумя другими таблицами, это можно сделать с помощью 1 таблицы (сужение может быть выполнено на base_table.role, а не на object.type) –

+0

Далее, 4) большой запрос выполняет ключевой поиск для каждой строки, ко всем таблицам сущностей, тогда как в версии UNION ALL поиск ключей выполняется только для соответствующего объекта. Предположим, что M строк, N сущностных таблиц, это поиск MxN для большого запроса, тогда как только M ищет запрос UNION ALL. Ваш вывод о том, что ваша версия, по крайней мере, настолько же эффективна или более результативна, не учитывает достаточно критериев или правильных критериев. Предполагая подходящий INDEX на base_table.role, моя оценка заключается в том, что моя версия, вероятно, будет работать лучше, чем большой запрос. –

+0

@TT. Помните, что каждое соединение может быть параллельным. Поскольку у меня одинаковое количество объединений, так как у вас есть ПОЛНЫЕ ЗАПРОСЫ, мой должен быть таким же или лучше. У вас есть дополнительное соединение для каждого запроса (к объекту) и дополнительный фильтр (где o.type = x). У меня есть призыв к COALESCE. Это действительно сводится к тому, насколько хорошо оптимизирован COALESCE. По моему опыту это быстрее, чем дополнительный запрос по DB2, но не на SQL Server, но это действительно зависит от многих факторов. – Hogan

2

Что вы, вероятно, захотите сделать, это следующее : для каждой возможной подробной таблицы (т. е. возможных значений в [object.value]), напишите запрос, который связывается только с одной подробной таблицей и должен иметь условие WHERE, чтобы ограничить соответствующие объекты. Затем выполните UNION ALL для всех этих запросов.

Скажите, что у вас есть Person, Legal Person и Counterpart как возможные значения в [object.type]. Предположим, что таблицы подробностей имеют одинаковые имена. Вы можете написать:

SELECT 
    bt.*, 
    dt.f1, 
    -- ..., 
    dt.fn 
FROM 
    base_table AS bt 
    INNER JOIN object AS o ON o.id = bt.role 
    INNER JOIN Person AS dt ON dt.entity_id = bt.entity_id 
WHERE 
    o.type='Person' 
UNION ALL 
SELECT 
    bt.*, 
    dt.f1, 
    -- ..., 
    dt.fn 
FROM 
    base_table AS bt 
    INNER JOIN object AS o ON o.id = bt.role 
    INNER JOIN [Legal Person] AS dt ON dt.entity_id = bt.entity_id 
WHERE 
    o.type='Legal Person' 
UNION ALL 
SELECT 
    bt.*, 
    dt.f1, 
    -- ..., 
    dt.fn 
FROM 
    base_table AS bt 
    INNER JOIN object AS o ON o.id = bt.role 
    INNER JOIN Counterpart AS dt ON dt.entity_id = bt.entity_id 
WHERE 
    o.type='Counterpart' 
+1

Я думаю, вы пропустили точку .. '[object.type]' на самом деле является значением в таблице 'object'. – JamieD77

+0

Я думаю, что вы, возможно, пропустили что-то - [object.type] - это столбец из таблицы объектов. – Sh4d0wsPlyr

+0

@ Sh4d0wsPlyr jinx – JamieD77

Смежные вопросы