【问题标题】:How can I group data by id and get the median value using SQL?如何按 id 对数据进行分组并使用 SQL 获取中值?
【发布时间】:2021-09-15 13:41:26
【问题描述】:

我有一张表格,上面有给定商店在几天内开业的时间,如下所示(OPENING_HOUR 设置为 24 小时时间格式,因此表格上的所有时间都是上午)。

>>> BUSINESS_HOURS
    DATE       | STORE_ID | OPENING_HOUR
________________________________________
0   2021-06-01 |   222    |  11
1   2021-06-02 |   222    |  11
2   2021-06-03 |   222    |  11
3   2021-06-04 |   222    |  11
4   2021-06-05 |   222    |  11
5   2021-06-06 |   222    |  11
6   2021-06-07 |   222    |  12
7   2021-06-08 |   222    |  11
8   2021-06-09 |   222    |  11
9   2021-06-10 |   222    |  12

现在我需要按 id 对数据进行分组,并确定哪个 opening_hour 最频繁。在下面的案例中,80% 的案例都在上午 11 点,所以我需要这样的东西:

>>> DATA_GROUPED
    STORE_ID   | OPENING_HOUR | FREQUENCY
________________________________________
0   222        |   11         |  0.8

这可能只使用 SQL 吗?谢谢你们的帮助,伙计们!

【问题讨论】:

    标签: sql database google-bigquery databricks


    【解决方案1】:

    你可以使用窗口函数:

    select store_id, opening_hour, count(*) as cnt,
           count(*) * 1.0 / sum(count(*)) over () as ratio
    from t
    where store_id = 1
    group by store_id, opening_hour
    order by cnt desc
    limit 1;
    

    如果您希望所有商店都使用此功能,可以使用窗口函数:

    select t.* except (seqnum)
    from (select store_id, opening_hour, count(*) as cnt,
                count(*) * 1.0 / sum(count(*)) over () as ratio,
                row_number() over (partition by store_id order by count(*) desc) as seqnum
         from t
         group by store_id, opening_hour
        ) t
    where seqnum = 1;
    

    【讨论】:

      【解决方案2】:

      我找到了一种使用窗口函数和 CTE 的方法。

      WITH Q1 AS (
        SELECT
          DISTINCT STORE_ID,
          OPENING_HOUR,
          COUNT(OPENING_HOUR) AMOUNT,
          ROW_NUMBER() OVER(PARTITION BY STORE_IDORDER BY COUNT(OPENING_HOUR) DESC) as RANK
        FROM T1
        GROUP BY 1, 2
      )
      
      SELECT
        STORE_ID,
        OPENING_HOUR,
        ROUND((AMOUNT/SUM(AMOUNT) OVER(PARTITION BY STORE_ID)),2) AS SHARE
      FROM Q1-- WHERE RANK = 1
      

      不是最短的答案,但效果很好!

      【讨论】:

        【解决方案3】:

        带开窗功能,这一种解决方案:

        WITH business_hours as (
        SELECT DATE("2021-06-01") as date, 222 as store_id, 11 as opening_hour
        UNION ALL
        SELECT "2021-06-02", 222, 11
        UNION ALL
        SELECT "2021-06-03", 222, 11
        UNION ALL
        SELECT "2021-06-04", 222, 11
        UNION ALL
        SELECT "2021-06-05", 222, 11
        UNION ALL
        SELECT "2021-06-06", 222, 11
        UNION ALL
        SELECT "2021-06-07", 222, 12
        UNION ALL
        SELECT "2021-06-08", 222, 11
        UNION ALL
        SELECT "2021-06-09", 222, 11
        UNION ALL
        SELECT "2021-06-10", 222, 12)
        
        , agg as (SELECT DISTINCT store_id, opening_hour,
        COUNT(store_id) OVER (partition by opening_hour, EXTRACT(MONTH FROM date)) as total_open_per_hour,
        COUNT(store_id) OVER (partition by EXTRACT(MONTH FROM date)) as total_open,
        from business_hours)
        
        SELECT store_id, opening_hour, safe_divide(total_open_per_hour, total_open) frequency FROM agg
        

        结果:

        【讨论】:

          【解决方案4】:

          考虑以下方法

          select * from (
            select distinct store_id, opening_hour, 
              count(1) over(partition by opening_hour) / count(1) over() frequency
            from business_hours
          )
          where true 
          qualify row_number() over(partition by store_id order by frequency desc) = 1      
          

          为您提供每家商店最频繁的营业时间

          如果应用于您问题中的样本数据 - 输出是

          【讨论】:

            猜你喜欢
            • 2020-07-26
            • 1970-01-01
            • 2012-12-19
            • 2021-11-17
            • 2013-04-18
            • 2015-10-15
            • 1970-01-01
            • 2016-02-17
            • 1970-01-01
            相关资源
            最近更新 更多