2016-12-21 4 views
1

uid,datevalueのテーブルがあります。グループ内の最も古いレコードと最も多くのレコードを合計するにはどうすればよいですか?

私はuidでグループ化し、最も早く見つかったvalueと最新のvalueとの間で異なるものを取得したいと考えています。 ActiveRecordで、あるいは単にSQLでこれをどうすればできますか?

例データ:

UID DATE  VALUE 
------------------------------ 
a | 2016-10-01 | 5 
a | 2016-8-01 | 10 
a | 2016-12-01 | 15 
b | 2016-10-01 | 5 
b | 2016-8-01 | 10 
c | 2016-12-01 | 15 

望ましい結果

UID DELTA (absolute value)  
------------------------------ 
a | 5 
b | 5 
c | 15 
+1

親愛なる、データセットおよび所望の結果セットを追加します。あなたは350の質問を書いています、これをより良く書いてください;) –

+0

私は希望の結果をa = 10と思いますか? –

+2

@ Mr.Bhosaleそれは一番早くない – GurV

答えて

3
select uid, abs(max(latest) - max(first)) diff 
from 
(select uid, 
    case when (row_number() over 
      (partition by uid order by date asc)) = 1 
      then value end first, 
    case when (row_number() over 
      (partition by uid order by date desc)) = 1 
      then value end latest 
from table 
) t 
group by uid; 
2

私はActiveRecordのを経験していないんだけど、普通のSQLには、最初と最後のレコードを検索するrow_numberウィンドウ関数を使用することができます。例:

WITH first_and_last AS (
    SELECT uid, 
      value, 
      ROW_NUMBER() OVER (PARTITION BY uid ORDER BY date ASC) as r_asc 
      ROW_NUMBER() OVER (PARTITION BY uid ORDER BY date DESC) as r_desc 
    FROM mytable) 
SELECT a.uid, a.value - b.value 
FROM first_and_last a 
JOIN first_and_last b ON a.uid = b.uid AND a.r_desc = 1 AND b.r_asc = 1 
0

あなたはfirst_value()および/またはlast_value()を使用し、その後、集約前のウィンドウ関数を使用しようとしている場合は、次の場合は、

select uid, abs(max(value_first) - max(value_last)) as diff 
from (select uid, 
      first_value(value) over (partition by uid order by date asc) as value_first, 
      first_value(value) over (partition by uid order by date desc) as value_last 
     from table 
    ) t 
group by uid; 

あなたはまた、すべてのサブクエリせずにこれを行うことができます配列集約関数を使用したいとします。行セットにcuid一列のみのようなケースを処理するために必要な最後のクエリで

0
with 
    t(i,d,v) as (
    values 
     ('a'::text, '2016-10-01'::date, 5::int), 
     ('a', '2016-08-01', 10), 
     ('a', '2016-12-01', 15), 
     ('b', '2016-10-01', 5), 
     ('b', '2016-08-01', 10), 
     ('c', '2016-12-01', 15)), 
    e as (
    select distinct on (i) * from t order by i, d), 
    l as (
    select distinct on (i) * from t order by i, d desc) 
select 
    e.i, 
    abs(e.v - case when e.d=l.d then 0 else l.v end) as diff 
from 
    e join l using(i); 

case(あなたが使用できるように、もちろんそれは、同じ日付で複数の行とのケースを処理しません " id 'が存在する場合)。

0

これを確認してください。

 select distinct a.UID, 
     -- ,a."VALUE",b."VALUE", 
     abs(coalesce (a."VALUE",0)-coalesce(b."VALUE",0)) 
     AS "DELTA (absolute value)" 
     from 
     (select * from 
     (select UID,"VALUE",ROW_NUMBER() over(PARTITION by uid order by rnk desc) as rnk from 
     (
     select UID,"VALUE", date,ROW_NUMBER() over(PARTITION by uid order by (select 1))as rnk 
     from edata 
     )a )a where rnk='1')a 
     left join 
     (select * FROM 
     (select UID,"VALUE",ROW_NUMBER() over(PARTITION by uid order by rnk desc) as rnk from 
     (
     select UID,"VALUE", date,ROW_NUMBER() over(PARTITION by uid order by (select 1))as rnk 
     from edata 
     ) 
     b)b where b.rnk=2)B 
     on a.uid=b.uid ORDER BY UID 

また、postgresql Demoを試してください。

上記のコードは、SQLサーバーとpostgresqlで正常に動作しています。

出力:

enter image description here

関連する問題