Делать «близко к» таким же, как «равный» в соединении - PullRequest
2 голосов
/ 14 января 2012

Я использую DB2 в этом случае, но я полагаю, что у этого есть общий ответ SQL. Я максимально упростил данные. Я рассчитываю на действия под названием «Претензии». Каждая претензия имеет уникальный номер претензии. Каждое действие имеет временную метку в формате «хммм». На самом деле, я не считаю действия, я считаю действия: в большинстве случаев один человек выполняет одно действие по одной заявке, а это одно действие. Но иногда человек выполняет несколько действий над одной заявкой, разделенных несколькими секундами или минутами: это также может быть одна сессия действия. Но если кто-то выполнил действие по заявке в 10:00, а затем выполнил действие по той же заявке в 13:00, это были бы два сеанса действий. Для моих целей временной интервал для того, что делает что-то одним сеансом действия против двух сеансов действия, составляет 3 часа, но это, конечно, произвольно. И нет никакого беспокойства о том, что окно открывается через полночь. Кроме того, у меня есть доступ только для чтения к этим данным, и я должен сделать это в одном утверждении. Спасибо.

Итак, вот некоторые данные (Таблица: ДЕЙСТВИЯ):

CLAIM_NO ACTTIME
AA       1424
BB       1134
CC       1221
DD       1425
DD       1512
EE       1619
FF       0928
FF       1518
GG       1348
HH       1332
II       1350

Я бы хотел превратить это в

CLAIM_NO ACTTIME
AA       1424
BB       1134
CC       1221
DD       1425
EE       1619
FF       0928
FF       1518
GG       1348
HH       1332
II       1350

(Обратите внимание, что вторая запись DD исчезла, но вторая запись FF все еще там).

Я выполнил это, присоединив таблицу к себе, при этом CLAIM_NO равно, а ACTTIME - между 3 часами ранее и 1 минутой раньше. Это позволяет мне получить строки, которые не принадлежат, и затем я использую EXCEPT для их устранения.

with excepto as (
 select a.claim_no, b.acttime
 from actions a 
 join actions b
 on a.claim_no=b.claim_no 
  and a.acttime between (b.acttime-300) and (b.acttime-1)
)
select * from actions except select * from excepto

Но я бы хотел сделать это с одним соединением, поэтому нет необходимости "кроме". Это в надежде на то, что производительность будет лучше: у моих реальных данных будет больше столбцов, которые используются исключением, и, конечно, больше строк. И это, кроме оператора, кажется, сильно замедляет запрос. Я использую множество временных таблиц с помощью оператора with, и они кажутся намного медленнее, чем сумма их частей.

Ответы [ 2 ]

3 голосов
/ 14 января 2012

Предполагая, что acttime - это целочисленный столбец:

select *
from (
   select claim_no,
          acttime, 
          acttime - lag(acttime, 1, acttime) over (partition by claim_no order by acttime) as diff
   from actions
) t
where diff = 0 or diff > 300
order by claim_no
0 голосов
/ 19 января 2012

Я чувствую себя немного глупо, забыв об этом ...

Вам не нужен except - есть доступное объединение под названием exception, которое делает именно то, что вы хотите (и яиспользовал его интенсивно):

SELECT a.claim_no, a.acttime
FROM actions as a
EXCEPTION JOIN actions as b
ON b.claim_no = a.claim_no
AND b.acttime >= a.acttime - 300
AND b.acttime < a.acttime

Получает вам набор результатов:

claim_No     acttime
============================
AA           1,424 
BB           1,134 
CC           1,221 
DD           1,425 
EE           1,619 
FF             928 
FF           1,518 
GG           1,348 
HH           1,332 
II           1,350 

(к сожалению, это не приведет к сокращению для ситуаций, когда кто-то вносит изменения впо крайней мере, один раз каждые 3 часа - будет отображаться только первый.Я считаю, что вам нужно что-то вроде 6-стороннего самообъединения минимум , чтобы обнаружить правильные записи, и это тоже немного запутанно; выможет повезет больше с этой стороной приложения)

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