2015-08-13 5 views
0

Я довольно новичок в Oracle SQL Queries и столкнулся с проблемой, которую я могу как решить, так и плохо описать в строке поиска Google/StackOverflow, чтобы найти ответ.Расширенный SQL-запрос - универсальная временная таблица или что-то еще?

У меня есть две таблицы.

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

 
|Order |Feature| 
|1  |  A| 
|1  |  B| 
|1  |  C| 
|2  |  B| 
|2  |  C| 
|3  |  A| 
|3  |  C| 
|4  |  A| 
|4  |  B| 

Таблица B содержит переменную Order и переменную даты. В этом случае переменная Order является уникальной.

 
|Order |  Date| 
|1  | Aug 1st| 
|2  | Aug 1st| 
|3  | Aug 1st| 
|4  |July 31st| 

Вот сложная часть (для меня). Я хочу таблицу А, но без каких-либо приказов, что:

  1. Не содержит экземпляр Feature «А»
  2. Падения в августе месяца в таблице B

Это будет выглядеть так:

 
|Order |Feature| 
|1  |  A| 
|1  |  B| 
|1  |  C| 
|3  |  A| 
|3  |  C| 

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

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

Любые мысли?

ответ

1

Существует несколько способов выполнить это (объединение с GROUP BY, IN, EXISTS, ANY), ни один из которых не требует временных таблиц или аналогичных техник.

Я выбираю, потому что легко следовать.

Select order, feature 
From tableA a 
WHERE a.Order in (select order from TableA where Feature = 'A') 
and a.order in (select order from tableB where be extract(month from date) = 8 ) 
+0

Вам не нужно, и порядок не равен нулю. Вы путаете IN с NOT IN, где nulls действительно может быть проблемой. –

+0

Я думаю, что 'month (date)' должен быть 'extract (month from date)' в Oracle. –

+0

@ThorstenKettner doh, что правильно, не знаю, что я думал –

0

Я думаю, вам нужно сделать подзапрос, чтобы найти порядок по вашим критериям, а затем выбрать нужную вам информацию.

Попробуйте это:

SELECT a.order, a.feature 
FROM tableA a 
INNER JOIN (SELECT DISTINCT a1.order 
      FROM tableA a1 
      INNER JOIN tableB b 
       ON b.order = a1.order 
      WHERE month(b.date) = 8 
       AND a1.feature = 'A' 
      ) c on c.order = a.order; 
0

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

Как написано в вашем вопросе, я думаю, что это то, что вы после:

with table_a as (select 1 ord, 'A' feature from dual union all 
       select 1 ord, 'B' feature from dual union all 
       select 1 ord, 'C' feature from dual union all 
       select 2 ord, 'B' feature from dual union all 
       select 2 ord, 'C' feature from dual union all 
       select 3 ord, 'A' feature from dual union all 
       select 3 ord, 'C' feature from dual union all 
       select 4 ord, 'A' feature from dual union all 
       select 4 ord, 'B' feature from dual), 
    table_b as (select 1 ord, to_date('01/08/2015', 'dd/mm/yyyy') dt from dual union all 
       select 2 ord, to_date('01/08/2015', 'dd/mm/yyyy') dt from dual union all 
       select 3 ord, to_date('01/08/2015', 'dd/mm/yyyy') dt from dual union all 
       select 4 ord, to_date('31/07/2015', 'dd/mm/yyyy') dt from dual union all 
       select 5 ord, to_date('31/07/2015', 'dd/mm/yyyy') dt from dual), 
     res as (select ta.ord, 
         ta.feature, 
         max(case when ta.feature = 'A' then 'A' end) over (partition by ta.ord) a_present, 
         tb.dt 
       from table_a ta 
         inner join table_b tb on (ta.ord = tb.ord)) 
select ord, 
     feature 
from res 
where a_present is not null 
and to_char(dt, 'mm') != '08'; 

     ORD FEATURE 
---------- ------- 
     4 A  
     4 B 

Однако, результаты, которые вы указали показать, что вы на самом деле хотели результаты, которые содержавший «A» в каждой группе и сделал падение в августе месяце

with table_a as (select 1 ord, 'A' feature from dual union all 
       select 1 ord, 'B' feature from dual union all 
       select 1 ord, 'C' feature from dual union all 
       select 2 ord, 'B' feature from dual union all 
       select 2 ord, 'C' feature from dual union all 
       select 3 ord, 'A' feature from dual union all 
       select 3 ord, 'C' feature from dual union all 
       select 4 ord, 'A' feature from dual union all 
       select 4 ord, 'B' feature from dual), 
    table_b as (select 1 ord, to_date('01/08/2015', 'dd/mm/yyyy') dt from dual union all 
       select 2 ord, to_date('01/08/2015', 'dd/mm/yyyy') dt from dual union all 
       select 3 ord, to_date('01/08/2015', 'dd/mm/yyyy') dt from dual union all 
       select 4 ord, to_date('31/07/2015', 'dd/mm/yyyy') dt from dual union all 
       select 5 ord, to_date('31/07/2015', 'dd/mm/yyyy') dt from dual), 
     res as (select ta.ord, 
         ta.feature, 
         max(case when ta.feature = 'A' then 'A' end) over (partition by ta.ord) a_present, 
         tb.dt 
       from table_a ta 
         inner join table_b tb on (ta.ord = tb.ord)) 
select ord, 
     feature 
from res 
where a_present is not null 
and to_char(dt, 'mm') = '08'; 

     ORD FEATURE 
---------- ------- 
     1 A  
     1 B  
     1 C  
     3 A  
     3 C 
0

Если вы не знакомы с аналитической функции и подзапросы (вы должны быть, но ваш вопрос означает, что вы не могли бы быть), вы можете сделать это с прямой присоединяется - ничего особенного:

SELECT a2.ord, a2.feature 
FROM table_a a1 
inner join table_b b on b.ord = a1.ord 
inner join table_a a2 on a2.ord = a1.ord 
where b.dt between to_date('01-AUG-2015') and last_day(to_date('01-AUG-2015') + (86399/86400)) 
and a1.feature = 'A'; 

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

Ваше сообщение не указывало, может ли один заказ иметь одну и ту же функцию дважды. Я предполагаю, что нет, но если да, тогда вам нужно выбрать SELECT DISTINCT вместо SELECT.

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

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

  • Нет связанных вопросов^_^