2015-02-04 3 views
1

Я использую t-sql.Хронологические сравнения в строках в T-SQL

У меня есть простая таблица называется mytable

Это выглядит следующим образом:

ID Num Date 
1  0  2015-01-01 00:00:00 
1  0  2015-01-02 00:00:00 
1  1  2015-01-03 00:00:00 
1  2  2015-01-04 00:00:00 
2  0  2015-01-01 00:00:00 
2  1  2015-02-01 00:00:00 
2  0  2015-03-01 00:00:00 
3  1  2014-01-01 00:00:00 
3  2  2014-01-02 00:00:00 
4  2  2015-02-01 00:00:00 
4  0  2015-02-02 00:00:00 
4  2  2015-02-05 00:00:00 

Ситуация с этой таблицей просто, что в любое время значение 1 или 2 были введены в таблицу, значения, которые появляются позже (хронологически), не могут быть 0. Это ошибка ввода данных и должна быть исправлена ​​путем изменения 0 на 2.

Таким образом, в упрощенном примере выше ID имеет ошибку для пользователя 2 и 4.

Для человека 2, кто-то ключом в 0 на 2015-01-01 00:00:00, в то время как для человека, кто-то 4 шпонкой в ​​0 на 2015-01-01 00:00:00.

Я новичок в SQL и честно хотел бы просто экспортировать все это как csv, открыть его в R, найти проблемы, а затем обновить значения с помощью инструкции обновления в базе данных. Но я чувствую, что это возможность поправиться на SQL - к сожалению, я застрял.

Здесь мне нужно каким-то образом сравнить строки внутри таблицы друг с другом, так как они являются групповыми по ID, но также учитывать эту хронологическую ситуацию. Я пробовал декартовое соединение с оператором CASE, который не работал. Любая помощь будет принята с благодарностью.

+1

Какая версия SQL Server вы используете? –

+0

7.0. Да, я работаю над очень старой системой. –

+0

Вы хотите только 0 записей или что-то меньшее, чем предыдущая запись? – Hogan

ответ

2

Этот запрос будет выбрать все проблемные записи:

SELECT * 
FROM mytable AS t 
WHERE Num = 0 AND EXISTS (SELECT 1 
          FROM mytable 
          WHERE Num IN (1,2) AND ID = t.ID AND Date < t.Date) 

Он выбирает все Num=0 записи, которые имеют либо Num=1илиNum=2предшествующую запись для одной и той же ID.

Выход:

ID Num Date 
------------------ 
2 0 2015-03-01 
4 0 2015-02-02 

Чтобы обновить таблицу просто сделать:

UPDATE mytable 
SET Num = 2 
FROM mytable AS t 
WHERE Num = 0 AND EXISTS (SELECT 1 
          FROM mytable 
          WHERE Num IN (1,2) AND ID = t.ID AND Date < t.Date) 
+0

, можете ли вы объяснить, что означает 'SELECT 1'? Каково использование номера '1'? –

+0

@ MattO'Brien 'SELECT 1' означает, что для каждой записи' mytable' выбирается только '1', удовлетворяющая критериям предложения WHERE. Это все, что нам нужно для «EXISTS»! –

0

Вы можете присоединиться к столу обратно к себе и поставить логику, как это:

select * 
from mytable t 
join mytable p on t.id = p.id 
        and t.date > p.date 
        and t.num < p.num 

это даст вам «лишние» строки, если есть более одного предшествующего шага м. Чтобы это исправить, можно сгруппировать по:

select id, Date, max(priornum) as max_prior 
from (
    select t.id, t.Date, p.num as priornum 
    from mytable t 
    join mytable p on t.id = p.id 
       and t.date > p.date 
       and t.num < p.num 
) sub 
group by id, Date 

или использовать снова и различны (для более современных версий серверных):

select distinct t.id, t.num, t.Date, 
       max(p.num) OVER (partition by t.id, t.Date) as max_prior 
from mytable t 
join mytable p on t.id = p.id 
       and t.date > p.date 
       and t.num < p.num 
Смежные вопросы