2016-11-28 100 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 

我創造了它谷歌搜索,並通過各種網站去後。 感謝大家的幫助。