2

私は次の情報を持っています(ビューごとに戻ります):

DateTime   ItemID  UserTyp Seconds

2012-01-01 10      S       12      

2012-01-01 10      S       18  

2012-01-01 11      S       22  

2012-01-02 11      M       52  

2012-01-02 10      S       120  

2012-01-02 11      S       NULL  

2012-01-03 15      M       112  

2012-01-03 12      S       182  

2012-01-04 10      M       NULL  

私がする必要があるのは、ユーザーの種類ごとにすべての秒の合計を計算することですが、5 期間分です。

期間は次のように設定されます。

  1. 最初と最後の日付を取得する
  2. すべての日を 5 日に分割
  3. 除算の結果は、1 つの期間に含まれる日数です。

次に、期間ごとに、レコードの DateTime と UserType に応じて、次のレコードを作成する必要があります。

Periods  UserTypeS_SUM(Seconds) UserTypeM_SUM(Seconds)
1        
2        
3
4
5

また、分割を行う前に、少なくとも 5 つのレコードがあるかどうかを確認する必要があります。たとえば、4 つある場合は、1 つのピリオドのみが使用されます。

見た目はそれほど変わらないことはわかっています。関数を使用してソリューションを作成し始めましたが、効果がないように見えます。これを簡単に実行できる組み込み関数はありますか?

編集:本当に申し訳ありませんが、ビューまたはテーブル値関数でこれを行う必要があることを忘れていました。この場合、ストア プロシージャは許可されません。

4

2 に答える 2

2

これを試して:

;with cte as(
select *,NTILE(5) over(order by [DateTime]) as period 
from Table1
),
type_S as( select period,SUM([Seconds]) as UserTypeS_SUM
 from cte
 where [UserTyp]='S'
 group by period),
type_M as( select period,SUM([Seconds]) as UserTypeM_SUM
 from cte
 where [UserTyp]='M'
 group by period),
 seq as (
  select 1 as sno union all
  select 2 union all
  select 3 union all
  select 4 union all
  select 5  )
 select  seq.sno as period,UserTypeS_SUM, UserTypeM_SUM
 from seq 
 left join  type_s s
 on seq.sno=s.period
 left join type_m m
 on seq.sno=m.period


SQL フィドルのデモ

于 2012-10-19T08:41:22.713 に答える
1

ここでクエリ:

データの作成:

create table #t (d DateTime,   ItemID  int,  UserTyp char(1), Seconds int);
insert into #t
values     
('2012-01-01', 10,      'S',       12      ),
('2012-01-01', 10,      'S',       18  ),
('2012-01-01', 11,      'S',       22  ),
('2012-01-02', 11,      'M',       52  ),
('2012-01-02', 10,      'S',       120  ),
('2012-01-02', 11,      'S',       NULL  ),
('2012-01-03', 15,      'M',       112  ),
('2012-01-03', 12,      'S',       182  ),
('2012-01-04', 10,      'M',       NULL );

--to other users: be free to take it for your own reply

クエリ: @Manatherin コメントにより編集

;with 

one_to_five as (
   select 1 as n union all
   select 2 as n union all
   select 3 as n union all
   select 4 as n union all
   select 5 as n
),

max_min as (
  select UserTyp, max(d) as max_d, min(d) as min_d
  from #t
  group by UserTyp),

time_for_period as (
  select UserTyp, datediff( second,  min_d, max_d ) / 5.0 as elapsed_time
  from max_min),
periods as (
select o2f.n, t4p.UserTyp, 
       dateadd(second ,elapsed_time * (n - 1)  ,mm.min_d ) as beginPeriod,
       dateadd(second ,elapsed_time * (n    )  ,mm.min_d ) as endPeriod
  from time_for_period t4p
 inner join max_min mm on t4p.UserTyp = mm.UserTyp
 cross join one_to_five o2f
 )
 select n, p.UserTyp, coalesce(sum( seconds ),0)
 from periods p
 left outer join #t t
    on t.UserTyp = p.UserTyp and 
    t.d between p.beginPeriod and p.endPeriod
 group by n, p.UserTyp
 order by 2,1;

結果

n UserTyp     
- ------- --- 
1 M       52  
2 M       0   
3 M       112 
4 M       0   
5 M       0   
1 S       52  
2 S       0   
3 S       120 
4 S       0   
5 S       182

この時点で、ユーザーごとにピボットする必要があります。

免責事項: クエリを作成しました。結果の一貫性を確認するために戻ることはありません。自由にデバッグしてください。

于 2012-10-19T08:16:57.260 に答える