【问题标题】:Postgres : Group by two columns - group by includes all unique combinations with 0 for null countsPostgres:按两列分组 - group by 包括所有唯一组合,空计数为 0
【发布时间】:2018-01-29 06:08:17
【问题描述】:

我有一个名为 case 的表,如下所示

os      device      event_time
Android     Mobile      <Tstamp>
Android     Tablet      <Tstamp>
Windows     PC          <Tstamp>
Linux       PC          <Tstamp>

我想要如下输出:

os         device    events_count
Android    Mobile      10
Android    Tablet      22
Android    PC          0
Windows    Mobile      0
Windows    Tablet      0
Windows    PC          40
Linux      Mobile      0
Linux      Tablet      0
Linux      PC          21

原始表不包含任何具有(Android、PC)、(Windows、Mobile)等组合的行,但我希望输出使这些行的计数为零。普通的 group by 查询没有给我这些可能是因为原始表根本没有这些组合。

select os, device, count(event_time)
from cases
group by os, device;

【问题讨论】:

    标签: sql postgresql group-by


    【解决方案1】:

    首先选择所有操作系统/设备组合,然后再次外部加入您的表:

    select o.os, d.device, count(e.events_count)
    from (select distinct os from events) o
    cross join (select distinct device from events) d
    left join events e on e.os = o.os and e.device = d.device
    group by o.os, d.device
    order by o.os, d.device;
    

    (不过,对于此类数据,您通常会有一个 OS 表和一个设备表。您可以交叉加入这些数据,然后外部加入您的事件表。)

    【讨论】:

    • 谢谢。我没有单独的“mytable”,其中包含操作系统和设备的所有可能的唯一组合。你是说我需要那个吗?我需要输出中 os 和 device 列中值的所有可能唯一组合。
    • 不,通常你会有一张包含所有操作系统的表。然后是另一个包含所有设备的表。您可能有第三张表,其中包含所有允许的组合,但如果允许任何组合,则该表没有任何意义。然后你会得到你的事件表,其中包含os_id(引用 OS 表中的记录)、device_id(引用设备表中的记录)和event_time
    • 好的。我没有单独的操作系统和设备表,因为我只需要操作系统和设备名称。无论如何,我修改了您的查询以使用单个事件表,如下所示:select devs.os, devs.device, count(e.events_count) from (select a.os, b.device from (select distinct os from events) a, (select distinct device from events) b) devs left join events e on e.os = devs.os and e.device = devs.device group by devs.os, devs.device order by devs.os, devs.device;
    • 操作系统和设备表将在那里确保数据完整性。例如。为了避免错别字。使用包含“Android”、“Windows”和“Linux”的操作系统表,您将避免使用“Andiod”或“Windos”的条目。另一个论点是,如果有一天有一个新的 Windows,并且您想将“Windows”重命名为“Windows(版本 10 和更早版本)”,您将在一个地方执行此操作,而不是在操作系统所在的数据库中的每条记录中执行此操作用过。
    • 您正确地纠正了我的问题。我一定是累了 :-) 当然,您必须选择不同的操作系统并将它们与不同的设备交叉连接。但是您使用的是我们在 1980 年代使用的连接语法,在 1992 年被 ANSI 连接取代之前。然后,当使用别名时,使用助记符。 ab 什么也不说。将此o 用于操作系统,将d 用于设备等。我已经更新了我的查询。
    【解决方案2】:

    我会使用cross join

    select t.os, t.device, count(c.os)
    from 
    (
      select os, device
      from
      (
        select distinct os from cases
      ) t1
      cross join 
      (
        select distinct device from cases
      ) t2
    ) t 
    left join cases c on t.os = c.os and 
                         t.device = c.device
    group by t.os, t.device
    

    【讨论】:

    • 你是对的;当然,我们需要操作系统和设备的交叉连接。当我什至提到必须这样做时,我不知道为什么我没有相应地编写查询。一定是累了;-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-06
    • 1970-01-01
    • 2014-09-28
    • 1970-01-01
    • 1970-01-01
    • 2019-08-07
    • 1970-01-01
    相关资源
    最近更新 更多