Redshift - 根据另一列C

时间:2017-12-19 05:21:06

标签: amazon-redshift

我有一个sql问题(在Redshift上),我需要根据index列中的最大值为列id中的每个ID获取列final_score的值并将其放入新列fav_index中的值。 score2等于score1 index n = index n + 1的值,例如,id = abc1index = 0score1 = 10 score2的值将是score1的值,其中index = 1和值final_score之间的差异是score1score2之间的差异。

如果你查看下表score,这会更容易。此表score是sql查询的结果,将在下面显示。

id    index   score1    score2    final_score
abc1  0       10        20        10
abc1  1       20        45        25
abc1  2       45        (null)    (null)
abc2  0       5         10        5
abc2  1       10        (null)    (null)
abc3  0       50        30        -20
abc3  1       30        (null)    (null)

因此,包含列fav_index的结果表应如下所示:

id    index   score1    score2    final_score    fav_index
abc1  0       10        20        10             0
abc1  1       20        45        25             1
abc1  2       45        (null)    (null)         0
abc2  0       5         10        5              0
abc2  1       10        (null)    (null)         0
abc3  0       50        30        -20            0
abc3  1       30        (null)    (null)         0

以下是从表score生成表story的脚本:

select
    m.id, 
    m.index, 
    max(m.max) as score1,
    fmt.score2,
    round(fmt.score2 - max(m.max), 1) as final_score
from
    (select
         sv.id,
         case when sv.story_number % 2 = 0 then cast(sv.story_number / 2 - 1 as int) else cast(floor(sv.story_number/2) as int) end as index,
         max(sv.score1)
    from
       story as sv
    group by
        sv.id,
        index,
        sv.score1
    order by
        sv.id,
        index
    ) as m
left join
    (select 
        sv.id, 
        case when sv.story_number % 2 = 0 then cast(sv.story_number / 2 - 1 as int) else cast(floor(sv.story_number/2) as int) end as index,
        max(score1) as score2
    from
        story as sv
    group by 
        id, 
        index
    ) as fmt
    on
        m.id = fmt.id
    and
        m.index = fmt.index - 1
group by
    m.id,
    m.index,
    fmt.score2

story如下:

id    story_number   score1
abc1  1              10
abc1  2              10
abc1  3              20
abc1  4              20 
abc1  5              45
abc1  6              45

我能想到的唯一解决办法是做一些像

这样的事情
select id, max(final_score) from score group by id

然后将其连接回上面的长脚本(用于生成表score)。我真的想避免编写这么长的脚本来获得我需要的一列额外信息。

有更好的方法吗?

谢谢!

更新:mysql中的答案也被接受。谢谢!

1 个答案:

答案 0 :(得分:0)

花了更多时间在这上面并询问周围的人,我终于通过参考这个窗口函数文档找出了解决方案 - PostgreSQL https://www.postgresql.org/docs/9.1/static/tutorial-window.html

我基本上在顶部添加了2个select语句,在最底部添加了1 x where语句。 where语句用于处理final_score = null的行,否则rank()函数会将它们排在1

我的代码变为:

select
    id, index, final_score, rank, case when rank = 1 then index else null end as fav_index
from
(select
    id, index, final_score, rank() over (partition by id order by final_score desc)
from
(select
    m.id, 
    m.index, 
    max(m.max) as score1,
    fmt.score2,
    round(fmt.score2 - max(m.max), 1) as final_score
from
    (select
         sv.id,
         case when sv.story_number % 2 = 0 then cast(sv.story_number / 2 - 1 as int) else cast(floor(sv.story_number/2) as int) end as index,
         max(sv.score1)
    from
       story as sv
    group by
        sv.id,
        index,
        sv.score1
    order by
        sv.id,
        index
    ) as m
left join
    (select 
        sv.id, 
        case when sv.story_number % 2 = 0 then cast(sv.story_number / 2 - 1 as int) else cast(floor(sv.story_number/2) as int) end as index,
        max(score1) as score2
    from
        story as sv
    group by 
        id, 
        index
    ) as fmt
    on
        m.id = fmt.id
    and
        m.index = fmt.index - 1
group by
    m.id,
    m.index,
    fmt.score2)
where
    final_score is not null)

结果如下:

id    index   final_score    rank     fav_index
abc1  0       10             2        (null)
abc1  1       25             1        1
abc2  0       5              1        0
abc3  0       -20            1        0

结果与我在问题中所说的略有不同,但是,每个id的fav_index都被识别出来,这正是我真正需要的。希望这可以帮助某人。干杯