На первый взгляд простой запрос в Pl Sql - PullRequest
1 голос
/ 12 января 2010

У меня есть таблица «дефекты» в следующем формате:

id   status  stat_date   line   div  area
1    Open    09/21/09    F      A    cube
1    closed  01/01/10    F      A    cube
2    Open    10/23/09    B      C    Back
3    Open    11/08/09    S      B    Front
3    closed  12/12/09    S      B    Front   

Моя проблема в том, что я хочу написать запрос, который просто извлекает «Открытые» дефекты.Если я напишу запрос, чтобы просто извлечь все открытые дефекты, то получу неправильный результат, потому что есть некоторые дефекты, с которыми связано 2 записи.Например, с запросом, который я написал, я получил бы дефекты с номерами 1 и 3 в своем результате, даже если они закрыты.Надеюсь, я хорошо объяснил свою проблему.Спасибо.

Ответы [ 5 ]

2 голосов
/ 12 января 2010

Использование:

SELECT t.*
  FROM DEFECTS t
  JOIN (SELECT d.id,
               MAX(d.stat_date) 'msd'
          FROM DEFECTS d
      GROUP BY d.id) x ON x.id = t.id
                      AND x.msd = t.stat_date
 WHERE t.status != 'closed'
  1. Соединение получает самую последнюю дату для каждого значения id.
  2. Присоединитесь к исходной таблице на основе id и date, чтобы получить только самые последние строки.
  3. Отфильтруйте те строки с закрытым статусом, чтобы узнать те, которые в данный момент открыты
1 голос
/ 12 января 2010
Select * 
from defects d
where status = 'Open'
and not exists (
   select 1 from defects d1
   where d1.status = 'closed'
   and d1.id = d.id
   and d1.stat_date > d.stat_date
)
1 голос
/ 12 января 2010

Таким образом, вы хотите получить самую последнюю строку для id, и из них выберите только те, которые открыты. Это разновидность общей проблемы наибольшее число групп .

Я бы сделал это так:

SELECT d1.*
FROM defects d1
LEFT OUTER JOIN defects d2
  ON (d1.id = d2.id AND d1.stat_date < d2.stat_date)
WHERE d2.id IS NULL
  AND d1.status = 'Open';
0 голосов
/ 13 января 2010

Этот запрос обрабатывает несколько открытий / закрытий / открытий, и только один проход через данные (то есть без самообъединений):

SELECT * FROM
(SELECT DISTINCT
        id
       ,FIRST_VALUE(status)
        OVER (PARTITION BY id
              ORDER BY stat_date desc)
        as last_status
       ,FIRST_VALUE(stat_date)
        over (PARTITION BY id
              ORDER BY stat_date desc)
        AS last_stat_date
       ,line
       ,div
       ,area
 FROM defects)
WHERE last_status = 'Open';
0 голосов
/ 12 января 2010

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

SELECT id FROM defects 
WHERE status = 'OPEN' AND id NOT IN 
(SELECT id FROM defects WHERE status = 'closed')
...