【问题标题】:Window function to select the name of the majority row in Redshift Postgres在 Redshift Postgres 中选择多数行名称的窗口函数
【发布时间】:2018-03-14 01:32:44
【问题描述】:

我有一个这样的数据集,其中一些行很有用,但已损坏。

create table pages (
  page varchar,
  cat varchar,
  hits int
);

insert into pages values
(1, 'asdf', 1),
(1, 'fdsa', 2),
(1, 'Apples', 321),
(2, 'gwegr', 30),
(2, 'hsgsdf', 2),
(2, 'Bananas', 321);

我想知道每个页面的正确类别以及总点击量。正确的类别是点击次数最多的类别。 我想要一个像这样的数据集:

page | category | sum_of_hits
-----------------------------
1    | Apples   |  324
2    | Bananas  |  353

我能得到的最远距离是:

SELECT page,
       last_value(cat) over (partition BY page ORDER BY hits) as category,
       sum(hits) as sum_of_hits
FROM pages
GROUP BY 1, 2

但它出错了:ERROR: column "pages.hits" must appear in the GROUP BY clause or be used in an aggregate function Position: 83

我尝试将点击数汇总 - ORDER BY max(hits) 但这没有意义,也不是我想要的。

小提琴:http://sqlfiddle.com/#!17/cb3c2/17

【问题讨论】:

    标签: sql amazon-redshift window-functions


    【解决方案1】:

    您似乎希望将点击次数的总和 设为最大值。这很容易:

    select page, sum(hits) as total_hits,
           max(case when seqnum = 1 then category end) as category
    from (select p.*,
                 row_number() over (partition by page order by hits desc) as seqnum
          from pages p
         ) p
    group by page;
    

    【讨论】:

      【解决方案2】:

      使用子查询:

      select page, cat, hits from
          (select page, cat, hits 
           ,max(hits) over (partition by page) as m_hits 
           from pages) t
      where m_hits = hits
      

      【讨论】:

        【解决方案3】:

        这里有两个问题:

        首先是last_value的用法。阅读Postgres documentation 中关于最后一个值的注释:

        请注意,first_value、last_value 和 nth_value 只考虑 “窗口框架”中的行,默认情况下包含行 从分区的开始到当前的最后一个对等点 排。这可能会给 nth_value 和 特别是最后一个值。您可以将框架重新定义为整体 通过在 UNBOUNDED PRECEDING 和 UNBOUNDED 之间添加 ROWS 进行分区 FOLLOWING 到 OVER 子句。有关详细信息,请参阅第 4.2.8 节。

        我建议你将其转换为 first_value:

        SELECT page,
               first_value(cat) over (partition BY page ORDER BY hits DESC) as category,
               hits
        FROM pages
        

        第二个问题是不能直接在GROUP BY子句中使用窗口函数,需要使用子查询或者cte:

        select page, category,
               sum(hits)
        from (
        SELECT page,
               first_value(cat) over (partition BY page ORDER BY hits DESC) as category,
               hits
        FROM pages
        ) a
        GROUP BY 1, 2
        

        SQL Fiddle

        【讨论】:

          【解决方案4】:

          在派生表中使用窗口函数first_value()hits 的相反顺序(FROM 子句中的子查询):

          select 
              page, 
              category,
              sum(hits) as sum_of_hits
          from (
              select
                  page,
                  first_value(cat) over (partition by page order by hits desc) as category,
                  hits
              from pages
              ) s
          group by 1, 2
          order by 1;
          

          SqlFiddle.

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-04-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多