Как я могу рассматривать запрос ОБЪЕДИНЕНИЯ как подзапрос

#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. Я попробовал это, и я могу получить только три дополнительных поля (кроме двух ключей). Это не полезно для меня в большинстве случаев