2016-09-29 18 views
0

我正在使用sqlserver。如何編寫一條sql語句將行拆分爲幾個部分並按時間求和時間

Table A: 
     ------------------------------------------------------- 
     | id | starttime    |  endtime   | 
     -------------------------------------------------------  
     | 9  | 2016-09-19 02:36:05 | 2016-09-19 03:02:16 |  
     | 9  | 2016-09-19 03:02:16 | 2016-09-19 09:26:15 | 
     | 9  | 2016-09-19 09:26:15 | 2016-09-20 01:18:02 | 

    Table B: 
     ---------------------------------------- 
     |partno |dayHourStart | dayHourEnd | 
     ---------------------------------------- 
     |3  |12:00:00.000 | 19:00:00.000 | 
     |3  |22:00:00.000 | 23:59:59.000 | 
     |3  |08:00:00.000 | 09:00:00.000 | 
     |1  |19:00:00.000 | 22:00:00.000 | 
     |1  |09:00:00.000 | 12:00:00.000 | 
     |2  |00:00:00.000 | 08:00:00.000 | 

現在,我想表A的行拆分成幾個部分,並通過部分總結的時候,按表B.每PARTNO的相應時間範圍,如何寫一個sql語句得到的結果如下:

Anticipant Result table: 
     --------------------------------------------------| 
     | id  |partno   | timeSum (minutes) | 
     |--------|-----------------|----------------------| 
     | 9  | 101    | 200    | 
     | 9  | 102    | 620    | 
     | 9  | 103    | 860    | 

任何想法,將不勝感激!謝謝。

+1

什麼是id - partno連接? – jarlh

回答

0
select a.id, b.partno, age(a.endtime, a.starttime) from a, b 

我認爲這應該做到這一點,至少在PostgreSQL上,但你可以擺弄它。

+0

我正在使用sqlserver。你能寫一個sqlserver的T-SQL語句嗎? – stkflmb12

+0

它應該是相同的,只是使用datediff函數而不是年齡。你甚至可以在幾分鐘內指定你想要它,所以datediff(分鐘,a.endtime,a.starttime)。 – Philip

+0

在表A中,從starttime到endtime在一行中有幾個部分,它需要將時間範圍分成一行。 – stkflmb12

1

這是棘手的,處理時間和日期時間和重疊。這裏有一個方法:

select a.id, b.partno, 
     datediff(minute, 
       (case when b.dayHourStart > cast(a.starttime as time) then b.dayHourStart 
         else cast(a.starttime as time) 
       end), 
       (case when b.dayHourEnd < cast(a.endtime as time) then b.dayHourEnd 
         else cast(a.endtime as time) 
       end) 
       ) as minutes 
from a join 
    b 
    on cast(a.starttime as time) <= b.dayHourEnd and 
     cast(b.endtime as time) >= b.dayHourStart; 

這種想法的唯一問題是最後的行爲A的。這跨越兩天。這隻會讓計算變得更加困難。您應該將該行分爲兩行:

| 9  | 2016-09-19 09:26:15 | 2016-09-19 23:59:59.000 | 
    | 9  | 2016-09-20 00:00:00 | 2016-09-20 01:18:02 | 
+0

首先非常感謝!您提供的方法可能無效。因爲在表A中可能有幾個部分連在一起,所以我們應該在表B中的相應時間範圍內將一行分成幾個部分,然後通過partno分組,例如
(例如,該行:2016-09-19 03:02:16 | 2016-09-19 09:26:15,可以分成(2016-09-19 03:02:16,2016-09-19 08:00:00](102),(2016-09-19 08: 00:00,2016-09-19 09:26:15](103) – stkflmb12

0

似乎很難通過使用sql語句來修復它,所以我寫了一個過程來解決此問題。你有什麼好主意嗎?特別是對於sql語句。

CREATE TABLE [dbo].[A] (
    [id] int NOT NULL , 
    [starttime] datetime NOT NULL , 
    [endtime] datetime NULL , 
    [status] int NULL , 
    PRIMARY KEY ([id], [starttime]) 
    ) 

    CREATE TABLE [dbo].[B] (
    [partno] int NULL , 
    [dayhourStart] varchar(255) NULL , 
    [dayHourEnd] varchar(255) NULL 
    ) 

    INSERT INTO [A] ([id], [starttime], [endtime], [status]) VALUES ('9', '2016-09-19 02:36:05.000', '2016-09-19 03:02:16.000', '1'); 
    INSERT INTO [A] ([id], [starttime], [endtime], [status]) VALUES ('9', '2016-09-19 03:02:16.000', '2016-09-19 09:26:15.000', '1'); 
    INSERT INTO [A] ([id], [starttime], [endtime], [status]) VALUES ('9', '2016-09-19 09:26:15.000', '2016-09-20 01:18:02.000', '1'); 

    INSERT INTO [B] ([partno], [dayhourStart], [dayHourEnd]) VALUES ('3', '12:00:00', '19:00:00'); 
    INSERT INTO [B] ([partno], [dayhourStart], [dayHourEnd]) VALUES ('3', '22:00:00', '23:59:59'); 
    INSERT INTO [B] ([partno], [dayhourStart], [dayHourEnd]) VALUES ('3', '19:00:00', '22:00:00'); 
    INSERT INTO [B] ([partno], [dayhourStart], [dayHourEnd]) VALUES ('1', '09:00:00', '12:00:00'); 
    INSERT INTO [B] ([partno], [dayhourStart], [dayHourEnd]) VALUES ('2', '00:00:00', '08:00:00'); 

    ALTER PROCEDURE [dbo].[uspSumTimeByPart] 
     AS 
     BEGIN 

      create table #resultTb(
       partno int, 
       starttime datetime, 
       endtime datetime, 
       sumtime float 
     ) 


      declare @id int,@starttime datetime,@endtime datetime; 
      declare @partno int,@dayHourStart VARCHAR(20),@dayHourEnd VARCHAR(20); 

      DECLARE crs_data CURSOR for SELECT id ,starttime ,endtime FROM a where status=1;    

      open crs_data ; 
      FETCH next FROM crs_data into @id ,@starttime ,@endtime ; 

      WHILE(@@fetch_status=0) BEGIN 
        --declare @daytimeStart datetime,@daytimeEnd datetime; 
        declare @daytimeStartStr VARCHAR(20),@daytimeEndStr VARCHAR(20); 
        set @daytimeStartStr = CONVERT(VARCHAR(10),@starttime,120); 
        set @daytimeEndStr = CONVERT(VARCHAR(10),@endtime,120); 


       DECLARE @tempdate VARCHAR(20) = @daytimeStartStr; 

        WHILE(DATEDIFF(ss, @tempdate, @daytimeEndStr) >= 0) BEGIN --iterate from @starttime to @endtime to get the day from it. 

           DECLARE crs_part CURSOR for SELECT partno,dayHourStart,dayHourEnd FROM b ; 
           open crs_part ; 
           FETCH next FROM crs_part into @partno,@dayHourStart,@dayHourEnd; 

           WHILE(@@fetch_status=0) BEGIN 
             declare @part_daytimeStart datetime,@part_daytimeEnd datetime; 

            set @part_daytimeStart = Cast(CONVERT(VARCHAR(10),@tempdate,120)+' '[email protected] as datetime); 
            set @part_daytimeEnd = Cast(CONVERT(VARCHAR(10),@tempdate,120)+' '[email protected] as datetime); 

            IF (NOT(@part_daytimeStart > @endtime or @part_daytimeEnd < @starttime)) BEGIN 
            declare @startdate datetime,@enddate datetime; 
            set @startdate = (case when @part_daytimeStart>[email protected] and @part_daytimeStart<[email protected] then @part_daytimeStart else @starttime end); 
            set @enddate = (case when @part_daytimeEnd <= @endtime and @part_daytimeEnd >= @starttime then @part_daytimeEnd else @endtime end); 

            INSERT into #resultTb(partno,starttime,endtime,sumtime) values (@partno, 
            @startdate,@enddate, DATEDIFF(minute, @startdate, @enddate)  
           ); 

             END 

              FETCH next FROM crs_part into @partno,@dayHourStart,@dayHourEnd; 

           END 

           CLOSE crs_part 
           DEALLOCATE crs_part; 

         set @tempdate = CONVERT(VARCHAR(10),DATEADD(dd, 1, @tempdate),120);  

       END 

       FETCH next FROM crs_data into @id ,@starttime ,@endtime ; 

      END 

     SELECT * FROM #resultTb 
      drop table #resultTb; 

      CLOSE crs_data; 
      DEALLOCATE crs_data; 

     END 
相關問題