#sql
Вопрос:
У меня есть набор таблиц, которые логически представляют собой одну таблицу, разделенную на части по соображениям производительности. Мне нужно написать запрос, который эффективно объединяет все таблицы вместе, поэтому я использую одно предложение where в результате. Я успешно использовал ОБЪЕДИНЕНИЕ в результате явного использования предложения WHERE в каждой подтаблице, как показано ниже
SELECT * FROM FRED_1 WHERE CHARLIE = 42 UNION SELECT * FROM FRED_2 WHERE CHARLIE = 42 UNION SELECT * FROM FRED_3 WHERE CHARLIE = 42
но поскольку существует десять отдельных подтаблиц, обновление предложения WHERE каждый раз вызывает боль. Чего я хочу, так это чего-то подобного
SELECT * FROM ( SELECT * FROM FRED_1 UNION SELECT * FROM FRED_2 UNION SELECT * FROM FRED_3) WHERE CHARLIE = 42
Если это имеет значение, запрос должен выполняться с базой данных DB2.
Вот более полная (очищенная) версия того, что мне нужно сделать.
select * from ( select * from FRD_1 union select * from FRD_2 union select * from FRD_3 ) as FRD, ( select * from REQ_1 union select * from REQ_2 union select * from REQ_3 ) as REQ, ( select * from RES_1 union select * from RES_2 union select * from RES_3 ) as RES where FRD.KEY1 = 123456 and FRD.KEY1 = REQ.KEY1 and FRD.KEY1 = RES.KEY1 and REQ.KEY2 = RES.KEY2
НОВАЯ ИНФОРМАЦИЯ:
Похоже, проблема больше связана с количеством полей в объединении, чем с чем-либо еще. Если я сильно ограничу поля, я смогу заставить работать большинство приведенных ниже вариантов синтаксиса. К сожалению, такое ограничение полей означает, что результирующий запрос, хотя и потенциально полезный, не дает мне желаемого результата. Мне удалось получить дополнительные 3 поля из одной из таблиц в дополнение к 2 ключам. Еще немного, и запрос завершится неудачей.
Комментарии:
1. Приводит ли этот синтаксис к ошибке? Если вы используете UNION ALL, а не UNION, это может сработать нормально. Затем вы представляете союзы в виде и заново изобретаете разделение…
2. Вы понимаете, что эта стратегия «раздели стол»-это определенный метод пессимизации?
3. На самом деле мне пришлось посмотреть, что означает пессимизация 🙂 Сказав это, идея разделить таблицу является частью приложения, которому около 10 лет, поэтому я мало что могу с этим поделать.
Ответ №1:
Я считаю, что вы должны дать имя результату вашего подзапроса. Я не знаю db2, поэтому я делаю снимок в темноте, но я знаю, что это работает на нескольких других платформах.
SELECT * FROM ( SELECT * FROM FRED_1 UNION SELECT * FROM FRED_2 UNION SELECT * FROM FRED_3) AS T1 WHERE CHARLIE = 42
Комментарии:
1. Это работает в простом случае одной группы таблиц (объединение), но не работает, если я хочу присоединиться к другой аналогичной группе T2
2. Выдает ли ваш исходный запрос ошибку или он просто не возвращает желаемые результаты?
3. Я получаю ошибку SQL0136, SQLCODE -136, SQLSTATE 54005, что означает «Слишком длинный ПОРЯДОК или ГРУППИРОВКА ПО столбцам». Проблема в том, что я получаю это, даже если у меня нет ЗАКАЗА или ГРУППЫ в моем запросе. Однако у меня есть 30 таблиц (3 группы по 10, каждая группа связана со следующей по ключу (T1.КЛЮЧ = T2.КЛЮЧ и T2.КЛЮЧ = T3.КЛЮЧ и T2.КЛЮЧ2 = T3.КЛЮЧ2))
4. можете ли вы опубликовать свой SQL, к которому вы пытаетесь присоединиться? Я делаю это (присоединяюсь к результату запроса) все время в DB2, и у меня нет проблем.
5. @Лесли добавил более подробную информацию в нижней части вопроса
Ответ №2:
Если логическая реализация представляет собой одну таблицу, а физическая реализация представляет собой несколько таблиц, то как насчет создания представления, определяющего логическую модель?
CREATE VIEW VW_FRED AS SELECT * FROM FRED_1 UNION SELECT * FROM FRED_2 UNION SELECT * FROM FRED_3
тогда это простой вопрос
SELECT * FROM VW_FRED WHERE CHARLIE = 42
Опять же, я не знаком с синтаксисом db2, но это дает вам общее представление.
Комментарии:
1. Это было бы здорово, если бы мне разрешили создавать представления… локально DB2, установленная на мэйнфрейме, «нуждается» в группе DB2 для «управления» всеми изменениями даже для разработчиков.
Ответ №3:
with FRD as ( select * from FRD_1 union select * from FRD_2 union select * from FRD_3 ), REQ as ( select * from REQ_1 union select * from REQ_2 union select * from REQ_3 ), RES as ( select * from RES_1 union select * from RES_2 union select * from RES_3 ) SELECT * from FRD, REQ, RES WHERE FRD.KEY1 = 123456 and FRD.KEY1 = REQ.KEY1 and FRD.KEY1 = RES.KEY1 and REQ.KEY2 = RES.KEY2
Комментарии:
1. Я получаю SQLCODE -136 SQLSTATE 54005 (ключ сортировки слишком длинный или содержит слишком много столбцов.), как только я включаю какие-либо объединения. Этот синтаксис работает, если я не указываю союзы.
Ответ №4:
Я не знаком с синтаксисом DB2, но почему вы не делаете это как INNER JOIN
или LEFT JOIN
?
SELECT * FROM FRED_1 INNER JOIN FRED_2 ON FRED_1.Charlie = FRED_2.Charlie INNER JOIN FRED_3 ON FRED_1.Charlie = FRED_3.Charlie WHERE FRED_1.Charlie = 42
Если значения не существуют в FRED_2 или FRED_3, используйте LEFT
/ OUTER JOIN
. Я предполагаю, что FRED_1-это главная таблица, и если запись существует, то она будет в этой таблице.
Комментарии:
1. На самом деле это таблица, разделенная на несколько частей 1-10. Ключ будет находиться в одной и только в одной из этих подтаблиц
Ответ №5:
может быть:
SELECT * FROM (select * from FRD_1 union select * from FRD_2 union select * from FRD_3) FRD INNER JOIN (select * from REQ_1 union select * from REQ_2 union select * from REQ_3) REQ on FRD.KEY1 = REQ.KEY1 INNER JOIN (select * from RES_1 union select * from RES_2 union select * from RES_3) RES on FRD.KEY1 = RES.KEY1 WHERE FRD.KEY1 = 123456 and REQ.KEY2 = RES.KEY2
Комментарии:
1. Я получаю ту же проблему (SQLSTATE 54005) при попытке этого и вариациях
2. ну а вам нужны все поля из каждой таблицы? может быть, указав конкретные поля, у вас не будет слишком много столбцов для ключа сортировки?
3. Я попробовал это, и я могу получить только три дополнительных поля (кроме двух ключей). Это не полезно для меня в большинстве случаев