【问题标题】:Select first row from group each by with count using Big Query使用 Big Query 从组中选择第一行
【发布时间】:2015-06-19 18:28:46
【问题描述】:

我在 BigQuery 中存储了超过 5 亿行,它们基本上代表了设备在特定时间的确切位置(不规则)。

我正在尝试找到一种快速有效的方法来确定设备的第一个和最后一个位置

到目前为止,我已经将它与连接一起使用,但它需要 10 多分钟才能完成(除非我只是查询中的限制)。我也尝试过使用 dense_rank 查询,但我无法对计数进行排序(而且我不完全理解它)。

我有一个 client_id、device_id(它是固定的,代表建筑物内的位置)和一个时间戳。

首先,我按 client_id 和 device_id 进行了分组,以验证我应该期待什么。然后我尝试使用最小和最大时间戳加入表格:

SELECT count(FirstSet.device_id), FirstSet.device_id
FROM
(
  SELECT client_id, device_id, created_at
  FROM [mytable.visitsv3]
  WHERE secret = 'xxx'
  GROUP each BY client_id, device_id, created_at
  ORDER BY client_id, created_at asc
  LIMIT 1000
) as FirstSet
inner join
(
  SELECT client_id, device_id, min(created_at)
  FROM [mytable.visitsv3]
  WHERE secret = 'xxx'
  GROUP each BY client_id, device_id, created_at
  LIMIT 1000
) SecondSet
on FirstSet.device_id = SecondSet.device_id
GROUP BY FirstSet.device_id
ORDER BY 1 DESC
limit 25

我是这个世界的新手,所以希望得到一些建议。正如我所说,更多的是性能,因为我们需要实时运行查询。

有很多关于相同概念的教程 - 我只是希望有人可以帮助优化。

--- 编辑 ---

输出格式应如下所示:

|count|device_id|
-----------------
|10000|      123|
| 9000|      345|
|  800|      234|

--- 在上下文中---

我们正在尝试使用我们的数据集实现许多目标(当然不是在单个查询中)。其中:

  • 创建最流行的进入和退出点的热图。

最初这只是一个总计,但从长期来看,我们必须了解在一天中的特定时间哪些进入/退出点很忙。然后使用相关函数进行一些预测分析。

  • 在穿过建筑物时创建客户的路径。

一旦我们有了入口点,我们就需要映射客户端所走的路径。同样,我们需要预测每天/每小时的行为等。

最初,我们只需要最流行的进入/退出点。出于这个原因,我们将客户分组在一起,并对他们出现的设备进行了计数。

数据如下:

client_id,device_id,created_at,start,end,duration,lat,lng
F047CA72E,0013BA30,2015-06-22 10:00:32 UTC,2015-06-22 09:30:31 UTC,2015-06-22 09:30:32 UTC,1,XX,YY
F40D8632F,00A30E00,2015-06-22 10:00:29 UTC,2015-06-22 09:30:26 UTC,2015-06-22 09:30:26 UTC,0,XX,YY
B808AA3E0,00138B20,2015-06-22 10:00:27 UTC,2015-06-22 09:30:25 UTC,2015-06-22 09:30:25 UTC,0,XX,YY
A0E532E96,00A33600,2015-06-22 10:00:34 UTC,2015-06-22 09:30:24 UTC,2015-06-22 09:30:25 UTC,1,XX,YY
D4F6F8D50,00149150,2015-06-22 10:00:34 UTC,2015-06-22 09:30:22 UTC,2015-06-22 09:30:22 UTC,0,XX,YY
70124EB7E,00A350A0,2015-06-22 10:00:33 UTC,2015-06-22 09:30:14 UTC,2015-06-22 09:30:14 UTC,0,XX,YY
200AF2A9E,00149090,2015-06-22 10:00:33 UTC,2015-06-22 09:30:13 UTC,2015-06-22 09:30:12 UTC,0,XX,YY
20AE4884A,0013EFC0,2015-06-22 10:00:30 UTC,2015-06-22 09:30:13 UTC,2015-06-22 09:30:13 UTC,0,XX,YY
CCD9BB01C,0013EFC0,2015-06-22 10:00:30 UTC,2015-06-22 09:30:12 UTC,2015-06-22 09:30:06 UTC,0,XX,YY
8CCE1F24E,0004165E,2015-06-22 10:00:12 UTC,2015-06-22 09:30:12 UTC,2015-06-22 09:30:12 UTC,0,XX,YY

每台设备的客户端数量在某种程度上是无关紧要的,因为无论如何它都会针对热图进行标准化。我们只需要对它们进行排名,以便我们可以看到最受欢迎和最不受欢迎。

【问题讨论】:

    标签: sql google-bigquery greatest-n-per-group


    【解决方案1】:

    让我重新表述一下我对设置的理解: - 设备安装在整个建筑物的固定位置 - 客户(人)在通过设备附近时穿过建筑物,记录此事件 - 带有client_id的客户端通过带有device_id的设备的时间记录在时间戳created_at中

    因此,给定客户的第一个 created_at 时间戳是她进入大楼的时间,相应的 device_id 将是一个入口点。要找到它,我们可以使用

    select 
      client_id, 
      first_value(device_id) 
         over(partition by client_id order by created_at asc) 
      as entry_device_id
    

    为了找到 10 个最受欢迎的条目,我们可以使用 TOP 和 COUNT(*),即

    select top(entry_device_id, 10), count(*)
    

    把它们放在一起:

    select top(entry_device_id, 10), count(*) from (
      select 
        client_id, 
        first_value(device_id) 
           over(partition by client_id order by created_at asc) 
        as entry_device_id
      from [mytable.visitsv3]
    )
    

    与出口点相同,但这次我们将使用 last_value 窗口函数:

    select top(exit_device_id, 10), count(*) from (
      select 
        client_id, 
        last_value(device_id) 
           over(partition by client_id order by created_at asc) 
        as exit_device_id
      from [mytable.visitsv3]
    )
    

    【讨论】:

    • 五。整洁的查询,但给出错误的输出。我需要将 aps 与计数 desc 分组。已更新 q。 S
    • 你能再澄清一下吗 - 原始问题要求提供设备的第一个和最后一个位置,但编辑后的版本要求计数。它是排在第一位还是排在最后还是其他位置?
    • 道歉莫莎,我应该更清楚。 (我怀疑需要两个查询。)我试图根据第一次和最后一次看到该位置的“入口”和“出口”点。每栋建筑都会有许多不同的可能性,这些可能性可以改变。想象一下走进一家医院,走过然后在另一端离开。我们将在多个点拿起设备,但总是有一个开始和结束。希望对您有所帮助。
    • 谢谢——“进入”和“退出”是有道理的——我仍然试图理解计数应该计算什么。输入数据的示例也会有所帮助:)
    • 让我在周末整理一些东西。简而言之,计数是找到最受欢迎的点。这就是我们按设备分组的原因。理想情况下,我们每分钟、每小时、每天、每周每月都会知道这些。虽然总数是我们开始的目标。
    猜你喜欢
    • 2017-02-14
    • 1970-01-01
    • 2011-11-12
    • 1970-01-01
    • 1970-01-01
    • 2020-06-25
    • 2014-01-17
    • 2012-10-28
    • 1970-01-01
    相关资源
    最近更新 更多