2015-08-11 2 views
2

У меня есть таблица под названием CHECKINOUT в SQL Server, таблица имеет следующие столбцы:Как Partition сложная таблица

PASSID CHECKTIME    CHECKTYPE UID 
-------------------------------------------------- 
PS3 2015-08-05 01:12:02.100  0  CAA0322 
PS3 2015-08-06 02:17:02.310  1  CAA0322 
PS4 2015-08-03 01:02:03.200  0  CAA0322 
PS4 2015-08-03 11:11:01.233  1  CAA0322 
PS3 2015-08-02 11:11:01.210  0  CAA0322 
PS3 2015-08-02 12:02:04.147  1  CAA0322 
PS1 2015-09-05 11:11:01.210  0  CAA0322 
PS1 2015-09-05 01:12:09.010  1  CAA0322 

PASSID является пропуск дается каждый раз, когда кто-то обращается в помещении и в тот момент, они пропустили, их Checkin время зарегистрировано и CheckType превращается в 0

CHECKTYPE=0 

Когда контроль помещений, время их проверку также снова регистрируются в checktime, но на этот раз флаг CheckType поворачивается к 1

CHECKTYPE=0 

теперь в конце дня я хотел бы видеть отчет о каждом проходе, независимо от того, сколько раз он пришел в и с выходом как

PASSID CheckInTime    CheckOutTime      UID 
PS1 2015-08-05 01:12:02.100  2015-08-06 02:17:02.310  CAA0322 
PS3 2015-08-05 01:12:02.100  2015-08-06 02:17:02.310  CAA0322 
PS3 2015-08-02 11:11:01.210  2015-08-02 12:02:04.147  CAA0322 
PS4 2015-08-03 01:02:03.200  22015-08-03 11:11:01.233 CAA0322 

выше, отображение результата предполагает следующее

  • CheckInTime является первым checktime с CheckType = 0 этого ID в
  • по алфавиту
  • CheckOutTime является первым checkti я с checktype = 1 этого ID в desc

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

declare @PassID varchar(30)='PS3'; 

with LastEntryData(PASSID, CHECKTIME, CHECKTYPE, GateID, UID) 
as 
(
    select top 2 
     c.PASSID, c.CHECKTIME, c.CHECKTYPE, c.GateID, c.UID  
    from 
     CHECKINOUT c 
    where 
     c.PASSID = @PassID 
    order by 
     c.CHECKTIME desc 
    ), 
    CheckInTime(CHECKTIME) as 
    (
     select 
      i.CHECKTIME 
     from 
      LastEntryData i 
     where 
      i.CHECKTYPE = 0), 
    CheckOutTime(CHECKTIME) as 
    (
     select 
      i.CHECKTIME 
     from 
      LastEntryData i 
     where 
      i.CHECKTYPE = 1) 
select 
    l.PASSID, CheckInTime = i.CHECKTIME, 
    CheckOutTime = o.CHECKTIME, l.UID 
from 
    LastEntryData l, CheckInTime i, CheckOutTime o 
group by 
    l.PASSID, l.GateID, l.UID, i.CHECKTIME, o.CHECKTIME 
+2

[Плохие привычки пинать: использование старого стиля JOIN и] (http://sqlblog.com/blogs/aaron_bertrand/archive/ 2009/10/08/bad-habits-to-kick-use-old-style-joins.aspx) - этот стиль таблиц * в стиле старого стиля * был заменен на * правильный * ANSI 'JOIN' синтаксис в ANSI - ** 92 ** SQL Standard (** более 20 лет ** назад), и его использование не рекомендуется –

+0

Разделы не имеют ничего общего с запросами, они обрабатывают физическое хранилище. –

+0

в любом случае я могу получить результат, как указано выше. – Bels

ответ

0

Давайте сделаем стол. (Вы получите больше ответов, если вы сделать это.)

create table checkinout (
    passid char(3) not null, 
    checktime timestamp not null default current_timestamp, 
    checktype integer not null check (checktype in (1, 0)), 
    uid char(7) not null 
); 

insert into checkinout values 
('PS3', '2015-08-05 01:12:02.100',  0,  'CAA0322'), 
('PS3', '2015-08-06 02:17:02.310',  1,  'CAA0322'), 
('PS4', '2015-08-03 01:02:03.200',  0,  'CAA0322'), 
('PS4', '2015-08-03 11:11:01.233',  1,  'CAA0322'), 
('PS3', '2015-08-02 11:11:01.210',  0,  'CAA0322'), 
('PS3', '2015-08-02 12:02:04.147',  1,  'CAA0322'), 
('PS1', '2015-09-05 11:11:01.210',  0,  'CAA0322'), 
('PS1', '2015-09-05 01:12:09.010',  1,  'CAA0322'); 

Я собираюсь сделать некоторые предположения, потому что ваши данные выборки не совпадают с ожидаемыми.

Этот запрос (в PostgreSQL) возвращает все время проверки.

select uid, passid, checktime as time_in 
from checkinout 
where checktype = 0 
order by uid, passid, checktime; 
 
uid  passid time_in 
-- 
CAA0322 PS1  2015-09-05 11:11:01.21 
CAA0322 PS3  2015-08-02 11:11:01.21 
CAA0322 PS3  2015-08-05 01:12:02.1 
CAA0322 PS4  2015-08-03 01:02:03.2 

подзапрос вернет время проверочные. Это будет работать практически с любыми SQL-dbms.

select 
    t1.uid, t1.passid, t1.checktime, 
    (select min(checktime) 
    from checkinout 
    where uid = t1.uid 
    and passid = t1.passid 
    and checktime >= t1.checktime 
    and checktype = 1) as time_out 
from checkinout t1 
where checktype = 0 
order by t1.uid, t1.passid, t1.checktime; 
 
uid  passid time_in     time_out 
-- 
CAA0322 PS1  2015-09-05 11:11:01.21 
CAA0322 PS3  2015-08-02 11:11:01.21 2015-08-02 12:02:04.147 
CAA0322 PS3  2015-08-05 01:12:02.1 2015-08-06 02:17:02.31 
CAA0322 PS4  2015-08-03 01:02:03.2 2015-08-03 11:11:01.233 

Неверные данные объясняет NULL.

Если ваши данные и ваши люди очень хорошо себя ведут, и если ваша платформа поддерживает аналитические функции, вы можете использовать либо lead(), либо lag(), чтобы собрать фрагменты. (Я думаю, что SQL Server 2012+ поддерживает инициативу() и запаздывание().)

with checkinout_extended as (
    select uid, passid, checktime as time_in, checktype, 
    lead(checktime) over (partition by uid, passid order by checktime, checktype) as time_out 
    from checkinout 
) 
select uid, passid, time_in, time_out 
from checkinout_extended 
where checktype = 0 
order by uid, passid, time_in; 
+0

Майк Шеррилл, вы только что спасли мой день. подзапрос - это то, что я искал, который может вернуть пропуск с помощью проверки даже тогда, когда этот человек еще не проверил – Bels