2016-03-31 8 views
1

дал следующую таблицу:SQL Server условный субтотальная запрос

create table #T 
    (
    user_id int, 
    project_id int, 
    datum datetime, 
    status varchar(10), 
    KM int 
    ) 

insert into #T values 
    (1, 1, '20160301 10:25', 'START', 1000), 
    (1, 1, '20160301 10:28', 'PASS', 1008), 
    (2, 2, '20160301 10:29', 'START', 2000), 
    (1, 1, '20160301 11:08', 'STOP', 1045), 
    (3, 3, '20160301 10:25', 'START', 3000), 
    (2, 2, '20160301 10:56', 'STOP', 2020), 
    (1, 4, '20160301 15:00', 'START', 1045), 
    (4, 5, '20160301 15:10', 'START', 400), 
    (1, 4, '20160301 15:10', 'PASS', 1060), 
    (1, 4, '20160301 15:20', 'PASS', 1080), 
    (1, 4, '20160301 15:30', 'STOP', 1080), 
    (4, 5, '20160301 15:40', 'STOP', 450), 
    (3, 3, '20160301 16:25', 'STOP', 3200) 

я должен суммировать длину дорожки между START и STOP, статусы для данного пользователя и проекта Ожидаемый результат будет таким:

user_id  project_id datum  TOTAL_KM 
----------- ----------- ---------- ----------- 
1   1   2016-03-01 45 
1   4   2016-03-01 35 
2   2   2016-03-01 20 
3   3   2016-03-01 200 
4   5   2016-03-01 50 

Как достичь этого без использования кластера? Производительность проблема (у меня есть более 1 миллиона записей в месяц, и мы должны хранить данные в течение нескольких лет)

Объяснение: Мы можем игнорировать записи со статусом «PASS». В принципе, мы должны вычесть значение KM записи START из записи STOP для данного пользователя и проекта. Там может быть несколько сот записей между запуском и остановками (как описана в данной выборке) Дата должна быть датой START (в случае, когда мы имеем над поставкой в ​​полночи)

Я думаю, что я должен иметь SELECT с предложением OVER(), но я не знаю, как сформулировать мой запрос для соблюдения этих условий.

Любая идея?

+0

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

+0

Sql server 2014 – Gabor

ответ

2
SELECT t.[user_id], 
     t.project_id, 
     cast(t.datum as date) as datum, 
     t1.KM- t.KM as KM 
FROM #T t 
INNER JOIN #T t1 
    ON t.[user_id]=t1.[user_id] and t.project_id = t1.project_id 
WHERE t.[status] = 'START' and t1.[status] = 'STOP' 
ORDER BY t.[user_id], 
     t.project_id, 
     cast(t.datum as date) 

Выход:

user_id  project_id datum  KM 
----------- ----------- ---------- ----------- 
1   1   2016-03-01 45 
1   4   2016-03-01 35 
2   2   2016-03-01 20 
3   3   2016-03-01 200 
4   5   2016-03-01 50 

(5 row(s) affected) 
+2

Если вы ищете только завершенные поездки, возможно, лучше сделать внутреннее соединение –

+0

@WyattShipman спасибо за подсказку! – gofr1

+0

Да, похоже, что сработает. Спасибо :-) – Gabor

0

Это может быть достигнуто простым подключением.

Один из примера: (это не может быть точно запрос, но только идея)

Select 
    a.user_id, 
    a.project_id, 
    b.datum as StartDate, 
    a.KM-b.KM as TotalKM 
From #T a 
Where status = 'STOP' 
Join 
(
    Select user_id, project_id, KM From #t Where 
    status = 'START' 
) b ON b.user_id = a.user_id, b.project_id = a.project_id 
#T b 
+0

Это не рабочий SQL-запрос ни в одном из диалектов базы данных. :-( – Gabor

+0

@Gabor, как я уже сказал, это была концептуальная идея, а не точный результат работы, который вы хотели, поэтому точка Посвящения просто потому, что вы ожидаете точного запроса. – rocky