【问题标题】:Redshift SQL: Column Counting Matching Rows Given a Condition within another columnRedshift SQL:在另一列中给定条件,对匹配行进行列计数
【发布时间】:2021-09-09 04:17:07
【问题描述】:

我有一个包含两列的表,用户 ID 和字符串。我想添加第三列,计算第二列中以任何给定行中的整个字符串值开头的字符串数。每个用户只有一行。

目标是得到如下表结构:

这里的计数等于字符串列中以该行中的给定值开头的行数。我尝试将 count(string like string + '%') 与 over(partition by string) 结合使用,但它似乎并没有像我希望的那样工作。

感谢任何帮助(顺便说一句,我在 Redshift 上使用 SQL)。

【问题讨论】:

    标签: sql database count amazon-redshift sql-like


    【解决方案1】:

    使用相关子查询:

    SELECT t1.ID, t1.String, 
           (SELECT COUNT(*) FROM tablename t2 WHERE t2.String LIKE CONCAT(t1.String, '%')) AS Count
    FROM tablename t1
    

    或者,使用自联接:

    SELECT t1.ID, t1.String, COUNT(*) AS Count
    FROM tablename t1 INNER JOIN tablename t2
    ON t2.String LIKE CONCAT(t1.String, '%')
    GROUP BY t1.ID, t1.String
    

    请参阅demo

    结果:

    id string count
    1 a 3
    2 ab 2
    3 abc 1
    4 d 3
    5 de 2
    6 def 1

    【讨论】:

    • 感谢您的帮助。这在演示中对我有用,但在实际的 redshift 数据库中,我收到此错误:“由于内部错误,不支持这种类型的相关子查询模式”。
    • @throwawaydisplayname 查询使用标准SQL,奇怪的是Redshift不支持。试试我的第二个查询。
    • 是的,我认为这可行,数据非常庞大,所以我仍在等待它运行,但如果它看起来不正确,我会再次发布。非常感谢@forpas。
    【解决方案2】:

    Redshift 中最快的方法可能是使用窗口函数。但是,它需要大量的冗长——因为您需要为每个字符串长度单独列:

    select t.*,
           (case when string = string_1
                 then count(*) over (partition by string_1)
                 when string = string_2
                 then count(*) over (partition by string_2)
                 when string = string_3
                 then count(*) over (partition by string_3)
            end)
    from (select t.*,
                 left(string, 1) as string_1,
                 left(string, 2) as string_2,
                 left(string, 3) as string_3
          from t
         ) t;
    

    嗯。 . .不需要子查询:

    select t.*,
           (case len(string)
                 when 1 then count(*) over (partition by left(string, 1))
                 when 2 then count(*) over (partition by left(string, 2))
                 when 3 then count(*) over (partition by left(string, 3))
            end)
    from t;
    

    【讨论】:

    • 您是否尝试过移除外壳并将 len(string) 放在 left() 函数中? "select , count() over (partition by left(string, len(string)) from t"
    • @BillWeiner。 . .那应该使用分区中每一行的长度,而不是每个分区一行。无论如何,这说明它不起作用:dbfiddle.uk/….
    • 足够真实 - 需要在窗口函数中使长度静态化。
    • 这个解决方案对我来说是最快的。谢谢戈登!
    • @throwawaydisplayname 是您所有最多 3 个字符的字符串吗?
    猜你喜欢
    • 2015-06-27
    • 1970-01-01
    • 2021-06-02
    • 1970-01-01
    • 1970-01-01
    • 2019-05-03
    • 2020-06-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多