Формирование запроса SQL для сравнения результатов по строкам - PullRequest
0 голосов
/ 05 января 2012

Постановка задачи:

выберите название всех магазинов, их статус, номера телефонов, дату вступления в силу чей номер телефона был изменен с 2003 года по настоящее время.

Схема

store_name,phone number , start_date , status

пример строк

    abc 1234  30-DEC-2011 open 
    abc 3433  04-Jan-2012 close
    bbb 4444  30-Jan-2010 open
    bbb 4444  31-Jan-2011 open

выход

    abc 1234 open 30-DEC-3011 till 3-Jan-2012
    abc 3433 close 04-Jan-2012 till date

У меня тоже все в порядке с двумя строками с отсортированной датой начала, как

abc 1234 30-DEC-2011 open
abc  3433 04-Jan-2012 close

bbb не следует сообщать, так как номер телефона не изменился. Мы должны сообщать только о тех магазинах, для которых был изменен номер телефона.

Может кто-нибудь помочь мне с этим запросом в Oracle? Я думаю, что с помощью коррелированных запросов это можно сделать, но я не уверен, как я могу построить один.

Обратите внимание, что в моей таблице содержится около 3154953 записей, поэтому мне также необходимо убедиться, что коррелированный запрос не блокирует таблицу на длительное время. Возможно ли это с Oracle?

Спасибо!


Ответ APC работает для меня только потому, что я вижу много повторений в моем результате.

Для ввода:

select store_name,phone_number,start_date, status where store_name=abc;

возвращает

STORE_name         Phone number start_date     STATUS
---------------- ---------------- ----------- ----------
abc              122 18-JAN-2011          open
abc              122 18-JAN-2011          open
abc              122 18-JAN-2011          close

выполнение вашего запроса дает мне следующий вывод.

abc              122 open from 18-JAN-2011 to 17-JAN-2011
abc              122 open from 18-JAN-2011 to 17-JAN-2011
abc              122 close  from 18-JAN-2011 to date

Можете ли вы объяснить, почему и где мисс?

Ответы [ 2 ]

2 голосов
/ 05 января 2012

Я предполагаю, что это для Oracle, а не MySQL, так как мое решение использует несколько магических приемов, которые, я уверен, недоступны в MySQL. Первое - это Common Table Expression, чтобы получить набор результатов, который мы можем использовать более одного раза. Второй - использование аналитической функции LEAD () для «прогнозирования» значений в следующей строке.

Итак, вот запрос:

with a as   ( select store_name
             , phone_number
             , status
             , start_date
             , lead (start_date, 1, trunc(sysdate)) over (partition by store_name
                                       order by start_date) as next_date
             , lead (phone_number, 1, null) over (partition by store_name
                                       order by start_date) as next_number
       from your_table 
       where start_date >= date '2003-01-01' ) 
select  a.store_name
      , a.phone_number
      , case  when a.next_date != trunc(sysdate) then 
                  a.status||' from '|| a.start_date ||' to '||to_char(a.next_date - 1)
               else a.status||' from '||a.start_date ||' to date'
              end  as status_text
from a
where a.store_name in (
                select store_name
                from a 
                where phone_number != next_number)
order by a.store_name, a.start_date
/

А вот и его вывод:

SQL> r
  1  with a as   ( select store_name
...
 22  order by a.store_name, a.start_date                
 23  /

STORE_NAME           PHONE_NUMBER STATUS_TEXT
-------------------- ------------ --------------------------------
abc                          1234 open from 30-DEC-11 to 03-JAN-12
abc                          3433 close from 04-JAN-12 to date

2 rows selected.

SQL> 

Что касается этого замечания:

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

Не имеет значения в Oracle, потому что чтение не блокирует другие чтения. На это тоже не пишут.

0 голосов
/ 05 января 2012

Это будет что-то вроде

select * from table0 as q0 join
(
    select min(date) from table0 as q1 where q1.store_name = q0.store_name
) as q2 on q2.store_name = q0.store_name
left join
(
    select max(date) from table0 as q1 where q1.store_name = q0.store_name
) as q3 on q3.store_name = q0.store_name

Это не совсем верно, поскольку у меня нет MySQL передо мной, но что-то в этом роде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...