2010-12-13 5 views
1

У меня есть запрос, который я хочу, чтобы упростить:MySQL - Как упростить этот запрос?

select 
     sequence, 
     1 added 
     from scoredtable 
     where score_timestamp=1292239056000 
     and sequence 
     not in (select sequence from scoredtable where score_timestamp=1292238452000) 
     union 
select 
     sequence, 
     0 added 
     from scoredtable 
     where score_timestamp=1292238452000 
     and sequence 
     not in (select sequence from scoredtable where score_timestamp=1292239056000); 

Любые идеи? в основном я хочу извлечь из той же таблицы все последовательности, которые различаются между двумя значениями метки времени. С «добавленным» коллом, который представляет, если строка является новой или если строка была удалена.

Источник таблицы:

score_timestamp    sequence 
1292239056000    0 
1292239056000    1 
1292239056000    2 
1292238452000    1 
1292238452000    2 
1292238452000    3 

Пример между (1292239056000, 1292238452000) результат запроса (2 строки):

sequence added 
3  1 
0  0 

Пример между (1292238452000, 1292239056000) Результат запроса (2 строки) :

sequence added 
0  1 
3  0 

Пример: (129 2239056000, 1292239056000) Результат запроса (0 строк):

sequence added 

ответ

2

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

SELECT 
    sequence, 
    CASE WHEN MIN(score_timestamp) = 1292239056000 THEN 0 ELSE 1 END AS added 
FROM scoredtable 
WHERE score_timestamp IN (1292239056000, 1292238452000) 
    AND (1292239056000 <> 1292238452000) -- No rows, when timestamp is the same 
GROUP BY sequence 
HAVING COUNT(*) = 1 

возвращает желаемый результат:

sequence added 
3  1 
0  0 
+0

+1 peter, я пропустил/испортил мое понимание этого :) –

+0

отлично! большое спасибо! –

+0

Упс! это не тот же запрос! Я добавил несколько примеров, которые не удовлетворяются этим запросом :(Например, при сравнении с той же меткой времени или при сравнении в порядке реверса (я хочу сравнить выше с более низкими отметками времени) .... –

0

Учитывая две временные метки

SET @ts1 := 1292239056000 
SET @ts2 := 1292238452000 

вы можете получить ваши дополнения и удаляет с:

SELECT s1.sequence AS sequence, 0 as added 
FROM scoredtable s1 LEFT JOIN 
    scoredtable s2 ON 
         s2.score_timestamp = @ts2 AND 
         s1.sequence = s2.sequence 
WHERE 
    s1.score_timestamp = @ts1 AND 
    s2.score_timestampe IS NULL 
UNION ALL 
SELECT s2.sequence, 1 
FROM scoredtable s1 RIGHT JOIN 
    scoredtable s2 ON s1.score_timestamp = @ts1 AND 
         s1.sequence = s2.sequence 
WHERE 
    s2.score_timestamp = @ts2 AND 
    s1.score_timestampe IS NULL 

в зависимости от количества строк и статистики cs приведенный выше запрос мог бы работать лучше, чем группировать по и иметь счет (*) = 1 (я думаю, что всегда будет нужно полное сканирование таблицы, в то время как вышеприведенный союз должен иметь возможность сделать 2 x anti-join, который может быть лучше)

Если у вас есть значительный набор данных, сообщите нам, что быстрее (тест с SQL_NO_CACHE для сопоставимых результатов)

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