2016-11-28 111 views
1

我有一个表格(tbl_user),其中包含用户(userid)的开始日期(start)和结束日期(end)。我想创建第二个表(tbl_minutes),每个用户的开始和结束之间的所有分钟(每分钟由用户标识)。这意味着在第二张表格中,我为每个用户在开始和结束之间的所有分钟。如何才能做到这一点?使用基于第二个表格的范围创建表格

我试过使用视图(见下文)。但服务器无法完成并中止。似乎太复杂了。

SELECT TOP (100) PERCENT dbo.view_users_woid.userID, dbo.view_users_woid.startdate, 
dbo.view_users_woid.enddate, dbo.view_minutes.datetime 
FROM dbo.view_minutes 
INNER JOIN dbo.view_users_woid 
ON dbo.view_minutes.datetime >= dbo.view_users_woid.startdate 
    AND dbo.view_minutes.datetime <= dbo.view_users_woid.enddate 
ORDER BY dbo.view_users_woid.userID, dbo.view_minutes.datetime 
+1

先试一下,然后问一个问题。 SO不会为你编码。 – Sachith

+0

你为什么要这样做? –

+0

首先我尝试使用一个视图(见下文)。但服务器无法完成并中止。似乎太复杂了。 SELECT TOP(100)PERCENT dbo.view_users_woid.userID,dbo.view_users_woid.startdate,dbo.view_users_woid.enddate, dbo.view_minutes.datetime FROM dbo.view_minutes INNER JOIN dbo.view_users_woid ON dbo.view_minutes.datetime> = dbo.view_users_woid.startdate AND dbo.view_minutes.datetime <= dbo.view_users_woid.enddate ORDER BY dbo.view_users_woid.userID,dbo.view_minutes.datetime – avidan

回答

1

可以使用DATEDIFF计算分两个日期之间的区别:

DATEDIFF(mi, date1, date2) 

我假设你知道如何对您的数据运行此功能,并使用INSERT将其添加到第三个表,但如果不是,请给我留言。

+0

我没有问题来计算差异。但是我想根据第二个表格为每个用户创建一个包含日期差异的表格。像“Foreach”。 – avidan

+0

如果你想*创建*表,你可以使用SELECT INTO。因此,使用SELECT语句定义新表格数据的形状,并在SELECT之后使用INTO创建并插入此数据。 (显然这只会工作一次,因为表格下一次运行时就已经存在了。) –

+0

@MarkWilliams您的答案不会给出任何提示,如何在开始和结束时间点之间创建每分钟的行... – Shnugo

0

试试这样说:

此功能将创建运行数字的派生表(最高可达10^9)无中生有快如闪电

CREATE FUNCTION dbo.RunningNumbers 
(
    @start INT 
    ,@count INT 
    ,@step INT 
) 
RETURNS TABLE 
AS 
RETURN 
WITH x AS(SELECT 1 AS N FROM(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS tbl(N))--10^1 
,N3 AS (SELECT 1 AS N FROM x CROSS JOIN x AS N2 CROSS JOIN x N3) --10^3 
,Tally AS(SELECT TOP(@count) (ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) + @start -1) * @step AS Nr FROM N3 
      CROSS JOIN N3 N6 CROSS JOIN N3 AS N9) 
SELECT Nr 
FROM Tally; 
GO 

- 这是与APPLY一起使用该功能的方法。该CTE将先切秒:

DECLARE @tbl_user TABLE(UserID INT IDENTITY,startTime DATETIME,endTime DateTime,note VARCHAR(100)); 
INSERT INTO @tbl_user VALUES 
({ts'2016-11-28 08:00:00'},{ts'2016-11-28 08:00:30'},'less than one') 
,({ts'2016-11-28 08:01:00'},{ts'2016-11-28 08:05:12'},'some minutes') 
,({ts'2016-11-28 23:50:00'},{ts'2016-11-29 00:10:23'},'over midnight'); 

WITH CutToNakedMinute AS 
(
    SELECT UserID 
      ,note 
      ,CONVERT(DATETIME,CONVERT(VARCHAR(17),startTime,126)+'00',126) AS StartMinute 
      ,CONVERT(DATETIME,CONVERT(VARCHAR(17),endTime,126)+'00',126) AS EndMinute 
    FROM @tbl_user AS u 
) 
SELECT UserID 
     ,note 
     ,StartMinute 
     ,DATEADD(MINUTE,steps.Nr,StartMinute) AS RunningMinute 
FROM CutToNakedMinute 
OUTER APPLY dbo.RunningNumbers(0,DATEDIFF(MINUTE,StartMinute,EndMinute)+1,1) AS steps 
GO 

--Clean-up for testing 

DROP FUNCTION dbo.RunningNumbers; 

结果

+--------+---------------+-------------------------+-------------------------+ 
| UserID | note   | StartMinute    | RunningMinute   | 
+--------+---------------+-------------------------+-------------------------+ 
| 1  | less than one | 2016-11-28 08:00:00.000 | 2016-11-28 08:00:00.000 | 
+--------+---------------+-------------------------+-------------------------+ 
| 2  | some minutes | 2016-11-28 08:01:00.000 | 2016-11-28 08:01:00.000 | 
+--------+---------------+-------------------------+-------------------------+ 
| 2  | some minutes | 2016-11-28 08:01:00.000 | 2016-11-28 08:02:00.000 | 
+--------+---------------+-------------------------+-------------------------+ 
| 2  | some minutes | 2016-11-28 08:01:00.000 | 2016-11-28 08:03:00.000 | 
+--------+---------------+-------------------------+-------------------------+ 
| 2  | some minutes | 2016-11-28 08:01:00.000 | 2016-11-28 08:04:00.000 | 
+--------+---------------+-------------------------+-------------------------+ 
| 2  | some minutes | 2016-11-28 08:01:00.000 | 2016-11-28 08:05:00.000 | 
+--------+---------------+-------------------------+-------------------------+ 
| 3  | over midnight | 2016-11-28 23:50:00.000 | 2016-11-28 23:50:00.000 | 
+--------+---------------+-------------------------+-------------------------+ 
| 3  | over midnight | 2016-11-28 23:50:00.000 | 2016-11-28 23:51:00.000 | 
+--------+---------------+-------------------------+-------------------------+ 
| 3  | over midnight | 2016-11-28 23:50:00.000 | 2016-11-28 23:52:00.000 | 
+--------+---------------+-------------------------+-------------------------+ 
| 3  | over midnight | 2016-11-28 23:50:00.000 | 2016-11-28 23:53:00.000 | 
+--------+---------------+-------------------------+-------------------------+ 
| 3  | over midnight | 2016-11-28 23:50:00.000 | 2016-11-28 23:54:00.000 | 
+--------+---------------+-------------------------+-------------------------+ 
| 3  | over midnight | 2016-11-28 23:50:00.000 | 2016-11-28 23:55:00.000 | 
+--------+---------------+-------------------------+-------------------------+ 
| 3  | over midnight | 2016-11-28 23:50:00.000 | 2016-11-28 23:56:00.000 | 
+--------+---------------+-------------------------+-------------------------+ 
| 3  | over midnight | 2016-11-28 23:50:00.000 | 2016-11-28 23:57:00.000 | 
+--------+---------------+-------------------------+-------------------------+ 
| 3  | over midnight | 2016-11-28 23:50:00.000 | 2016-11-28 23:58:00.000 | 
+--------+---------------+-------------------------+-------------------------+ 
| 3  | over midnight | 2016-11-28 23:50:00.000 | 2016-11-28 23:59:00.000 | 
+--------+---------------+-------------------------+-------------------------+ 
| 3  | over midnight | 2016-11-28 23:50:00.000 | 2016-11-29 00:00:00.000 | 
+--------+---------------+-------------------------+-------------------------+ 
| 3  | over midnight | 2016-11-28 23:50:00.000 | 2016-11-29 00:01:00.000 | 
+--------+---------------+-------------------------+-------------------------+ 
| 3  | over midnight | 2016-11-28 23:50:00.000 | 2016-11-29 00:02:00.000 | 
+--------+---------------+-------------------------+-------------------------+ 
| 3  | over midnight | 2016-11-28 23:50:00.000 | 2016-11-29 00:03:00.000 | 
+--------+---------------+-------------------------+-------------------------+ 
| 3  | over midnight | 2016-11-28 23:50:00.000 | 2016-11-29 00:04:00.000 | 
+--------+---------------+-------------------------+-------------------------+ 
| 3  | over midnight | 2016-11-28 23:50:00.000 | 2016-11-29 00:05:00.000 | 
+--------+---------------+-------------------------+-------------------------+ 
| 3  | over midnight | 2016-11-28 23:50:00.000 | 2016-11-29 00:06:00.000 | 
+--------+---------------+-------------------------+-------------------------+ 
| 3  | over midnight | 2016-11-28 23:50:00.000 | 2016-11-29 00:07:00.000 | 
+--------+---------------+-------------------------+-------------------------+ 
| 3  | over midnight | 2016-11-28 23:50:00.000 | 2016-11-29 00:08:00.000 | 
+--------+---------------+-------------------------+-------------------------+ 
| 3  | over midnight | 2016-11-28 23:50:00.000 | 2016-11-29 00:09:00.000 | 
+--------+---------------+-------------------------+-------------------------+ 
| 3  | over midnight | 2016-11-28 23:50:00.000 | 2016-11-29 00:10:00.000 | 
+--------+---------------+-------------------------+-------------------------+ 
+0

谢谢。我会尽力并会回来给你。 – avidan

+0

我收到一个错误:'无效的对象名称dbo.RunningNumbers',虽然函数存在 – avidan

+0

@avidan这应该工作...请显示您的代码! – Shnugo

0

你可以试试下面的查询

INSERT INTO tbl_minute 
SELECT userid, DATEDIFF(n, startdate, enddate) diff_in_minutes 
FROM tbl_user; 
+1

此答案不提供任何提示如何创建一个单行开始和结束之间的每一分钟... – Shnugo

0

一种方法是创建其插入到第二个表的触发器根据第一个表中的更改。

假设用户表具有低于数据

userid startdate enddate 
1  20161001 20161002 

现在再次假定tbl_minutes是以下格式

userid startdate enddate  mindata 

触发将是以下格式

create trigger trg_test 
on 
dbo.userid_test 
after insert 
as 
begin 

;with cte 
as 
(
select userid,startdate,enddate,dateadd(mi,1,startdate) as mindata from inserted i 
union all 
select userid,startdate,enddate,dateadd(mi,1,mindata) from 
cte c 
where dateadd(mi,1,mindata)<=enddate 
) 
insert into dbo.tbl_minutes 
select * 
from cte option(maxrecursion 0) 

end 

输出:

userid startdate   enddate    mindata 
1 2016-10-01 00:00:00.000 2016-10-02 00:00:00.000 2016-10-01 03:38:00.000 

当然,你要照顾修改触发更新

0

这是我的解决方案,它完美的作品:

declare @user_id int 

select @user_id = min(userid) from tbl_users 

while @user_id is not null 
begin 
    declare @maxmin int 
    declare @patid int 
    declare @minute as datetime 
    declare @iter2 int 
    declare @dateandtime datetime 
    set @maxmin=(select DATEDIFF(mi, AddmissionDate, DischargeDate) from tbl_users where userid = @user_id) 
    set @patid=(select userid from tbl_users where userid = @user_id) 
    set @dateandtime=(select addmissiondate from tbl_users where userid = @user_id) 
    set @iter2=0 

    while @iter2 <= @maxmin 

     BEGIN 

     insert into tbl_users_minutes(userid,dateandtime) 
     values (@patid,DATEADD(mi,@iter2,@dateandtime)) 

     SET @Iter2 = @Iter2 + 1 

    END 

select @user_id = min(userid) from tbl_users where userid > @user_id 


end 

我创造了它谷歌搜索,并通过各种网站去后。 感谢大家的帮助。