Запрос выдает декартово соединение

#sql #oracle #oracle11g

#sql #Oracle #oracle11g

Вопрос:

У меня есть запрос ниже, он возвращает 65000 строки.

  WITH msilk AS (
            SELECT
                k.inventory_item_id        AS inventory_item_id,
                k.organization_id          AS organization_id,
                k.primary_uom_code         AS primary_uom_code,
                k.concatenated_segments    AS concatenated_segments,
                t.description              AS description,
                t.language                 AS language
            FROM
                mtl_system_items_b_kfv  k,
                mtl_system_items_tl     t
            WHERE
                    k.inventory_item_id = t.inventory_item_id
                AND k.organization_id = t.organization_id)
        select * from msilk;
 

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

Эту with clause query переменную я использую дважды. По какой-то причине я должен удалить предложение with и воссоздать запрос. поскольку на эту переменную дважды ссылались с разными псевдонимами, я пишу ниже запрос и дважды использую таблицу с разными псевдонимами

    select count(*) from(  SELECT
            k.inventory_item_id        AS inventory_item_id,
            k.organization_id          AS organization_id,
            k.primary_uom_code         AS primary_uom_code,
            k.concatenated_segments    AS concatenated_segments,
            t.description              AS description,
            t.language                 AS language
        FROM
            mtl_system_items_b_kfv  k,
            mtl_system_items_b_kfv k1,
            mtl_system_items_tl     t,
            mtl_system_items_tl     t1
        WHERE 
               k.inventory_item_id = t.inventory_item_id and
               k1.inventory_item_id = t1.inventory_item_id AND
           k.organization_id = t.organization_id and
            k1.organization_id = t1.organization_id 
            );
 

Это также должно дать 65k записей, но это дает около 840k записей. правильно ли мое условие соединения? Мне нужен тот же результат, что и с запросом предложения.

По сути, я должен дважды ссылаться на обе таблицы.

Любое предложение действительно ценится.

Комментарии:

1. Вредные привычки: использование объединений в старом стиле — этот стиль списка таблиц, разделенных запятыми , в старом стиле был заменен соответствующим JOIN синтаксисом ANSI в стандарте SQL ANSI- 92 ( более 25 лет назад), и его использование не рекомендуется

2. спасибо Marc. link очень полезно. не могли бы вы, пожалуйста, помочь выше, пожалуйста

3. Перепишите свой запрос, чтобы использовать явные соединения, и не забудьте связать k с k1 и / или t с t1 🙂

4. Спасибо Arvo. существующие условия соединения верны? Мне нужно добавить только еще 2 И предложение .. верно?

5.@ShrutiSharma . . . Нет. В запросе, объединяющем n ON таблиц, должно быть n — 1 предложений. Использование запятых в FROM предложении просто приводит к тому типу проблем, с которыми вы сталкиваетесь.

Ответ №1:

Вы присоединились k и t , и вы также присоединились k1 и t1 , но вы не объединили эти две пары вместе, поэтому они создают CROSS JOIN , и ваш запрос эффективно:

 select count(*)
from   (
  SELECT k.inventory_item_id        AS inventory_item_id,
         k.organization_id          AS organization_id,
         k.primary_uom_code         AS primary_uom_code,
         k.concatenated_segments    AS concatenated_segments,
         t.description              AS description,
         t.language                 AS language
  FROM   mtl_system_items_b_kfv  k
         INNER JOIN mtl_system_items_tl t
         ON (   k.inventory_item_id = t.inventory_item_id
            AND k.organization_id   = t.organization_id
            )
         CROSS JOIN mtl_system_items_b_kfv k1
         INNER JOIN mtl_system_items_tl t1
         ON (   k1.inventory_item_id = t1.inventory_item_id
            AND k1.organization_id   = t1.organization_id )
);
 

Вам нужно выяснить, как соотнести k / t pair и k1 / t1 pair и изменить значение CROSS JOIN на an INNER JOIN . Однако в вашем вопросе недостаточно информации, чтобы мы могли рассказать вам, как это сделать; вам нужно будет определить, какие столбцы сопоставлять.

Что-то вроде:

 select count(*)
from   (
  SELECT k.inventory_item_id        AS inventory_item_id,
         k.organization_id          AS organization_id,
         k.primary_uom_code         AS primary_uom_code,
         k.concatenated_segments    AS concatenated_segments,
         t.description              AS description,
         t.language                 AS language
  FROM   mtl_system_items_b_kfv  k
         INNER JOIN mtl_system_items_tl t
         ON (   k.inventory_item_id = t.inventory_item_id
            AND k.organization_id   = t.organization_id
            )
         INNER JOIN JOIN mtl_system_items_b_kfv k1 -- changed to INNER
         ON (   k.some_column = k1.some_column )   -- added a join condition
         INNER JOIN mtl_system_items_tl t1
         ON (   k1.inventory_item_id = t1.inventory_item_id
            AND k1.organization_id   = t1.organization_id
            AND t.some_other_column  = t1.some_other_column ) -- added a join condition
);
 

Эту with clause query переменную я использую дважды. По какой-то причине я должен удалить предложение with и воссоздать запрос.

Это похоже на проблему XY, когда вы должны решать исходную проблему, а не пытаться обойти вторичные проблемы, созданные попыткой обойти первую проблему. Мое предложение состояло бы в том, чтобы решить, как обойти это ограничение, чтобы вам нужно было запрашивать таблицу только один раз и можно было избежать самосоединения; но, опять же, вы не предоставили никаких подробностей, поэтому мы не можем внести какие-либо предложения, чтобы помочь.

Комментарии:

1. большое вам спасибо. К сожалению, я не могу проголосовать, потому что у меня нет минимально необходимых 15 голосов.

2. сегодня получил 15 голосов, поэтому проголосовал за. этот ответ мне очень помог 🙂