PL/SQL — Oracle 9.1

Вот сценарий, над которым мы работаем здесь. У нас есть стол для клиентов и стол для продаж. Таблицы объединяются через идентификатор транзакции в пользовательской таблице.

Покупатель может купить любые фрукты в магазине.

Что нам нужно сделать, так это узнать, например: сколько клиентов купили яблок, прежде чем они купили вишни.

Table structure:

Cust - Cust ID, Transaction ID, ...
Sales - Transaction ID, Fruit ID, Insert date for record, ...

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

Итак, нам нужно найти, когда 1-е яблоко и 1-я вишня куплены cust, а затем проверить даты на них.


person sandy    schedule 25.05.2011    source источник
comment
Является ли идентификатор транзакции целым числом и логически увеличивается со временем?   -  person kevpie    schedule 26.05.2011
comment
это первичный ключ для таблицы продаж, целое число.   -  person sandy    schedule 26.05.2011


Ответы (2)


Я поддерживаю мнение Гэри о модели данных, но это не имеет отношения к вопросу.

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

select apple.cust_id
from
    ( select c.cust_id, min(s.sale_date) as sale_date
      from cust c
           join sales s 
                on s.transaction_id = c.transaction_id 
      where s.fruit_id = 'CHERRY'
      group by c.cust_id ) cherry
    ,     
    ( select c.cust_id, min(s.sale_date) as sale_date
      from cust c
           join sales s 
                on s.transaction_id = c.transaction_id 
      where s.fruit_id = 'APPLE'
      group by c.cust_id ) apple
where cherry.cust_id = apple.cust_id
and cherry.sale_date > apple.sale_date
/

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

select cust_id
from
    ( select c.cust_id
             , min(case when s.fruit_id = 'CHERRY' = s.sale_date else null end) as cherry_date
             , min(case when s.fruit_id = 'APPLE' = s.sale_date else null end) as apple_date
      from cust c
           join sales s 
                on s.transaction_id = c.transaction_id 
      group by c.cust_id ) cherry
where cherry_date > apple_date
/

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

person APC    schedule 26.05.2011

Как transaction_id может быть столбцом/атрибутом для клиента? Это означает, что у клиента может быть только одна транзакция.

Предполагая, что у вас есть таблица с customer_id, fruit_id и sale_date, вы можете попробовать

select cust_id,
       min(case when fruit_id = 'Apple' then sale_date end) first_apple_purchase,
       min(case when fruit_id = 'Cherry' then sale_date end) first_cherry_purchase
from transactions
group by cust_id
having min(case when fruit_id = 'Apple' then sale_date end) <
        min(case when fruit_id = 'Cherry' then sale_date end)
person Gary Myers    schedule 26.05.2011
comment
Спасибо за предложение, но в таблице клиентов есть один и тот же пользователь, выполняющий несколько транзакций. Таблица клиентов может быть, например: john, 1; Джон, 2 года; Джон, 3 года; Адам, 4; Адам, 5 лет; Питер, 6. идентификатор транзакции является ключом соединения ч/б двух таблиц. - person sandy; 26.05.2011
comment
Дизайн стола неудачный. Если у клиента может быть несколько транзакций, то в таблице Sales должен быть столбец customer_id, а не у Customer — столбец transaction_id. В противном случае одна и та же транзакция может иметь несколько записей о клиентах, указывающих на нее, что я не считаю желательным. - person Alanyst; 26.05.2011