如何在SQL Server中将每个数据拆分为总和100

时间:2015-02-27 18:00:41

标签: sql-server

如何分割数据,总和为100 我应该根据总值为100的日期插入数据 样品: http://prntscr.com/6ak0ji

1 个答案:

答案 0 :(得分:0)

谢谢,我自己找到了答案。或许可以帮助别人

CREATE TABLE [dbo].[tmp_event_with_location] (
  [event_id] bigint NOT NULL,
  [vehicle_id] int NULL,
  [position_id] bigint NULL,
  [date_time] datetime NULL,
  [event_type] smallint NULL,
  [object_id] int NULL,
  [x] int NULL,
  [y] int NULL,
  [duration] int NULL,
  [description] varchar(250) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
  [speed] int NULL,
  [speed_limit] int NULL,
  [location_id] int NULL,
  [odometer] int NULL,
  [trip_odometer] int NULL,
  [street_name] nvarchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
  [location_name] nvarchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
  [kecamatan] nvarchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
  [kabupaten] nvarchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
  [vehicle_name] varchar(30) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
  [geofence_code] varchar(20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
  [geofence_name] varchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
  [geofence_type] varchar(30) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
  [check_point_name] varchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
  [site_name] varchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
  [site_code] varchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
  [site_type] varchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
  [route_name] varchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
  [route_code] varchar(20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
  [event_type_desc] varchar(30) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
  [driver_name] varchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
  [engine] bit NULL,
  [stop_time_limit] int NULL,
  CONSTRAINT [tmp_event_with_location_pk_tmp_event_with_location] PRIMARY KEY CLUSTERED ([event_id])
    WITH (
      PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF,
      ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)
ON [PRIMARY]
GO

CREATE TABLE [dbo].[drum_duration] (
  [drum_id] int IDENTITY(1, 1) NOT NULL,
  [member_id] int NULL,
  [vehicle_id] int NULL,
  [vehicle_number] varchar(20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
  [alert_limit] int NULL,
  [alert_email] varchar(30) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
  [sensor_start_date] datetime NULL,
  [drum_date] datetime NULL,
  [duration] int NULL,
  [total_duration] int NULL,
  [create_date] datetime NULL,
  [create_by] int NULL,
  [note] varchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
  PRIMARY KEY CLUSTERED ([drum_id])
    WITH (
      PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF,
      ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)
ON [PRIMARY]
GO

程序:

SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE dbo.Aprocedure7
AS
BEGIN


--------------------------------------------------------------------------------  
/*
table to test
*/  
DECLARE @tmp_drum table
(
  vehicle_id int ,
  alert_limit int,
  drum_date datetime ,
  from_date datetime ,
  last_drum_date datetime ,
  total_duration int,
  duration int ,
  note varchar (100)

)
insert @tmp_drum(vehicle_id , alert_limit,drum_date,from_date,total_duration )
        select dd.vehicle_id,dd.alert_limit, dd.drum_date,from_date= case when dd.drum_date is null then dd.sensor_start_date 
        else dd.drum_date end,
        dd.total_duration
        from drum_duration dd

--------------------------------------------------------------------------------
/*
get data
*/     
DECLARE @tmp_table1 TABLE
( 
  vehicle_id int, 
  date_time datetime, 
  event_type int, 
  alert_limit int,
  drum_date datetime,
  myOrder int  
) 
insert @tmp_table1( vehicle_id  ,date_time ,event_type ,alert_limit,drum_date,myOrder )               
        select b.vehicle_id, b.date_time, b.event_type, d.alert_limit,d.drum_date,
        ROW_NUMBER() OVER (ORDER BY b.date_time) myOrder
        from tmp_event_with_location b
        inner join @tmp_drum d on  d.vehicle_id =b.vehicle_id
        where b.date_time >=d.from_date  
        and b.engine=1  and b.event_type in(68,69)

--------------------------------------------------------------------------------
/*
get the duration of the date
*/  

DECLARE @tmp_table2 TABLE
( 
  vehicle_id int, 
  date_time datetime, 
  event_type int, 
  datetime_2 datetime,
  event_type2 int,
  alert_limit int,
  drum_date datetime,
  duration int --,
 -- runing_total int 
)  
insert @tmp_table2 (  vehicle_id , date_time , event_type , datetime_2 ,
        event_type2, alert_limit,drum_date, duration  )                     
      select 
          m.vehicle_id,          
          m.date_time, 
          m.event_type,
          next.date_time as datetime_2, 
          next.event_type as event_type2,
          m.alert_limit,
          m.drum_date,
          convert(int,datediff(minute,m.date_time,next.date_time))as duration--sum row by date
                -- sum(convert(int,datediff(minute,m.date_time,next.date_time))) over(order by m.date_time rows between unbounded preceding and current row)  AS runing_total 
      from @tmp_table1 as m
      outer apply 
      (
        select TOP 1 next.vehicle_id, next.date_time, next.event_type
        from @tmp_table1 as next
        where next.myOrder > m.myOrder and next.event_type = 68 and isnull((select event_type from @tmp_table1 prev where prev.myOrder +1 = next.myOrder),69) = 69
        order by   next.date_time asc 
      ) as next
        where m.event_type = 69 and ISNULL((select event_type from @tmp_table1 prev where prev.myOrder+1 = m.myOrder),68) = 68                     
        and next.vehicle_id =m.vehicle_id   

-------------------------------------------------------------------------------- 
/*
get the sum of the duration of the next column
*/         
DECLARE @tmp_table3 TABLE
( 
  vehicle_id int, 
  date_time datetime, 
  event_type int, 
  datetime_2 datetime,
  event_type2 int,
  alert_limit int,
  drum_date datetime,
  duration int ,
  runing_total int 
)  
insert @tmp_table3 (  vehicle_id , date_time ,  event_type , datetime_2 , event_type2,  alert_limit,drum_date, duration, runing_total  )                     
    select  
      n.vehicle_id, 
      n.date_time, 
      n.event_type,
      n.datetime_2, 
      n.event_type2,
      n.alert_limit,
      n.drum_date,
      n.duration,
      (select cast(sum(duration) as char(50))  from @tmp_table2
        where datetime_2 <=n.datetime_2 and  vehicle_id =n.vehicle_id) as runing_total -- ? sum duration  nex row
       from @tmp_table2 as n
       group by   
      n.vehicle_id, 
      n.date_time, 
      n.event_type,
      n.datetime_2, 
      n.event_type2,
      n.alert_limit,
      n.drum_date,
      n.duration

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
/*
main cursor
*/

SET NOCOUNT ON
DECLARE  @c_vehicle_id int , @c_datetime_2 datetime,@alert_limit int, @c_runing_total int
DECLARE CURSOR_RUN  CURSOR FOR
    select  t2.vehicle_id,t2.datetime_2, t2.alert_limit ,t2.runing_total 
    from @tmp_table3 as t2  
    order by t2.vehicle_id,t2.datetime_2

OPEN CURSOR_RUN
FETCH NEXT FROM CURSOR_RUN INTO @c_vehicle_id , @c_datetime_2 ,@alert_limit, @c_runing_total   
  WHILE (@@FETCH_STATUS=0)
    BEGIN
     print @c_vehicle_id    
      IF(@c_runing_total<=@alert_limit)
        BEGIN
            update @tmp_drum set 
            last_drum_date= @c_datetime_2,
            duration =@c_runing_total , 
            --total_duration= total_duration +  @c_runing_total ,
            note= case when  @c_runing_total <= alert_limit then '-' else 'its duration exceeds the specified limit alerts'end                           
            where vehicle_id =@c_vehicle_id
            and @c_runing_total<=@alert_limit 
            and drum_date is not null --? calculated from the date of drum_date and do not exceed the limit alerts
        END            
      ELSE   
        BEGIN
            update @tmp_drum set 
            last_drum_date= @c_datetime_2,
            duration =@c_runing_total , 
            --total_duration= total_duration +  @c_runing_total ,
            note= case when  @c_runing_total <= alert_limit then '-' else 'counted from the start of pairs of sensors'end                            
            where vehicle_id =@c_vehicle_id
            and @c_runing_total>=@alert_limit --
            and drum_date is null --? sensors installed from the beginning and over the limit alerts
        END
    FETCH NEXT FROM CURSOR_RUN INTO @c_vehicle_id , @c_datetime_2 ,@alert_limit, @c_runing_total
  END
CLOSE CURSOR_RUN
DEALLOCATE CURSOR_RUN
SET NOCOUNT OFF

select * from @tmp_table3
select * from @tmp_drum
END