2009-08-20 7 views
0

Как можно получить следующие результаты(SQL Server 2008) - SQL вопрос о КТР и присоединяется :-(

user | date | login time | logoff time 

Я хотел бы распечатать каждый день в течение определенного периода времени с согласования входа и выхода? время, которое пишется история таблицы Если есть кратна Войти для того же пользователя и тот же день, то SQL следует выбрать минимальную дату для входа в систему и максимального срока для выхода из системы

Это пользователь стол..

CREATE TABLE [dbo].[User](
[id] [int] IDENTITY(1,1) NOT NULL, 
[username] [varchar](25) NOT NULL, 
[firstname] [nvarchar](50) NOT NULL, 
[lastname] [nvarchar](50) NOT NULL, 
CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED 
(
[id] ASC 
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

Это история таблица:

CREATE TABLE [dbo].[History](
[id] [int] IDENTITY(1,1) NOT NULL, 
[user_id] [int] NOT NULL, 
[login_time] [datetime] NOT NULL, 
[logoff_time] [datetime] NOT NULL, 
CONSTRAINT [PK_History] PRIMARY KEY CLUSTERED 
( 
[id] ASC 
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

До сих пор я могу распечатать, но только для одного пользователя:

date | login time | logoff time 

Это SQL (с использованием CTE на SQL Server 2008):

with CTE(d) as 
(
select d = convert(datetime, '20090801') 
union all 
select d = d + 1 from CTE where d < '20090831' 
) 

select 
d as date, 
(
    select min(h.login_time) 
    from history h 
    where 
     h.user_id = 1 and 
     h.login_time >= d and 
     h.login_time < dateadd(d, 1, d) 
) as login_time, 
(
    select max(h.logoff_time) 
    from history h 
    where 
     h.user_id = 1 and 
     h.logoff_time >= d and 
     h.logoff_time < dateadd(d, 1, d) 
) as logoff_time 
from CTE 
option (maxrecursion 370) 

я должен каким-то образом включить это, но я застрял :-(

select * 
from [user] u 
where 
exists (
    select * 
    from history h 
    where 
     h.user_id = u.id and 
     h.login_time >= '20090801' and 
     h.login_time < '20090901' 
) 

Вот пример данных в таблице истории:

id user_id login_time   logoff_time 
1 1 2009-08-20 06:00:01.000 2009-08-20 22:07:58.230 
2 1 2009-08-20 22:10:15.137 2009-08-20 23:15:15.000 
3 2 2009-08-20 22:08:20.103 2009-08-20 22:08:20.103 
4 2 2009-08-20 22:08:23.340 2009-08-20 22:08:23.340 
5 2 2009-08-21 14:30:30.120 2009-08-21 19:20:30.000 

Желаемая выход будет:

user date  login_time    logoff_time 
john 2009-08-01 NULL      NULL 
john 2009-08-02 NULL      NULL 
... 
john 2009-08-08 2009-08-20 06:00:01.000 2009-08-20 23:15:15.000 
... 
john 2009-08-31 NULL      NULL 
merry 2009-08-01 NULL      NULL 
merry 2009-08-02 NULL      NULL 
... 
merry 2009-08-20 2009-08-20 22:08:20.103 2009-08-20 22:08:23.340 
merry 2009-08-21 2009-08-21 14:30:30.120 2009-08-21 19:20:30.000 
... 
merry 2009-08-31 NULL      NULL 

ответ

0

Я решил эту проблему с помощью друга. Это решение:

with dates(a_date) as (
select a_date = convert(datetime, '20090801') 
union all 
select a_date = a_date + 1 from dates where a_date < '20090831' 
) 

select 
    u.username   as username, 
    d.a_date   as a_date, 
    min(h.login_time) as login_time, 
    max(h.logoff_time) as logoff_time 
from 
    dates d 
    cross join dbo.[User] u 
    left join dbo.History h ON 
u.id = h.user_id and 
h.login_time >= d.a_date and 
h.login_time < dateadd(d, 1, d.a_date)  
group by 
    u.username, 
    d.a_date 
order by 
    u.username 

Кроме того, второй, немного дольше:

with CTE(d) as 
(
select d = convert(datetime, '20090801') 
union all 
select d = d + 1 from CTE where d < '20090831' 
) 

select 
u.username, 
d as date, 
(
    select min(h.login_time) 
    from history h 
    where 
     h.user_id = u.id and 
     h.login_time >= d and 
     h.login_time < dateadd(d, 1, d) 
) as login_time, 
(
    select max(h.logoff_time) 
    from history h 
    where 
     h.user_id = u.id and 
     h.logoff_time >= d and 
     h.logoff_time < dateadd(d, 1, d) 
) as logoff_time 
from CTE 
cross join [User] u 
order by username, date 
Смежные вопросы