【问题标题】:how to use sql statement to process this data?如何使用 sql 语句来处理这些数据?
【发布时间】:2019-08-09 09:29:38
【问题描述】:

我有以下数据需要分析,我可以通过代码将数据处理成我需要的结果。但是我想知道我是否可以使用 SQL 来处理我需要的结果。

数据

| id  | phoneNum    | callType | created          |
| --- | ----------- | -------- | ---------------- |
| 1   | 15000000000 | 1        | 2019-08-07 01:02 |
| 2   | 15000000000 | 1        | 2019-08-07 02:03 |
| 3   | 15000000000 | 2        | 2019-08-07 04:05 |
| 4   | 15000000000 | 1        | 2019-08-07 05:07 |
| 5   | 15000000000 | 2        | 2019-08-07 06:07 |
| 6   | 15000000000 | 1        | 2019-08-07 06:20 |
| 7   | 15000000000 | 1        | 2019-08-07 06:30 |
| 8   | 15000000001 | 1        | 2019-08-07 07:07 |
| 9   | 15000000000 | 1        | 2019-08-07 08:07 |
| 10  | 15000000000 | 1        | 2019-08-08 08:07 |

成为

| phoneNum       | callType | created          | count |
| -------------- | -------- | ---------------- | ----- |
| 15000000000    | 1        | 2019-08-07 02:03 | 2     |
| 15000000000    | 2        | 2019-08-07 04:05 | 1     |
| 15000000000    | 1        | 2019-08-07 05:07 | 1     |
| 15000000000    | 2        | 2019-08-07 06:07 | 1     |
| 15000000000    | 1        | 2019-08-07 06:30 | 2     |
| 15000000001    | 1        | 2019-08-07 07:07 | 1     |
| 15000000000    | 1        | 2019-08-07 08:07 | 1     |
| 15000000000    | 1        | 2019-08-08 08:07 | 1     |

添加使用场合: 想象一下,当一个手机来电时,最后一个电话最终被插入到数据库中。这是数据的数据源。但是,当显示这个数据时,最后一次调用的数据应该显示在第一行。此时,将数据库中的第四行与第三行进行比较。由于来电类型不同,这个时间应该是独立于一条线路的;如果相同,则不进行处理,原始数据加一计数。

【问题讨论】:

  • 请解释一下phonenum如何在第3行变成15000000000(2)
  • 你的分组标准是什么?
  • @AnkitBajpai 感谢您的回复。 15000000000(2)表示前两个数据重复,按照callType分组。
  • 那为什么第1行和第3行没有组合在一起,那一定是3行呢?
  • @orangeChu 我不知道那个应用程序,具体来说,但我承认它看起来有点奇怪。为什么第 1、2、 4 行没有分组?另外,是什么决定了合并行的created 时间戳?

标签: sql sqlite optimization


【解决方案1】:

这似乎是一个孤岛问题。你可以用row_number()的区别来处理这个:

select phonenum, count(*) as cnt, type, max(created)
from (select t.*,
             row_number() over (partition by phonenum order by id) as seqnum,
             row_number() over (partition by phonenum, type order by id) as seqnum_t
      from t
     ) t
group by phonenum, type, (seqnum - seqnum_t);

注意:这会将计数放在单独的列中(这对我来说更有意义),而不是将其连接到电话号码上。

让我举例说明会发生什么:

  id  | phoneNum    | callType | created          | seqnum | seqnum_t
| --- | ----------- | -------- | ---------------- |--------|---------
| 1   | 15000000000 | 1        | 2019-08-08 01:02 |   1    |    1
| 2   | 15000000000 | 1        | 2019-08-08 02:03 |   2    |    2
| 3   | 15000000000 | 2        | 2019-08-08 04:05 |   3    |    1
| 4   | 15000000000 | 1        | 2019-08-08 06:07 |   4    |    1

现在的区别:

| id  | phoneNum    | callType | created          | seqnum | seqnum_t |
| --- | ----------- | -------- | ---------------- |--------|----------|
| 1   | 15000000000 | 1        | 2019-08-08 01:02 |   1    |    1     | 0
| 2   | 15000000000 | 1        | 2019-08-08 02:03 |   2    |    2     | 0
| 3   | 15000000000 | 2        | 2019-08-08 04:05 |   3    |    1     | 2
| 4   | 15000000000 | 1        | 2019-08-08 06:07 |   4    |    1     | 3

差异匹配您要查找的组。这通常是一个充分的例证。可以证明差异确实可以识别组。

编辑:

使用lag() 和累积总和可能更容易处理您修改后的问题:

select phonenum, count(*) as cnt, type, max(created)
from (select t.*,
             sum(case when prev_phonenum = phonenum and prev_type = type then 0 else 1 end) over (order by id) as grp
             row_number() over (partition by phonenum, type order by id) as seqnum_t
      from (select t.*,
                   lag(type) over (order by id) as prev_type,
                   lag(phonenum) over (order by id) as prev_phonenum
            from t
           )
     ) t
group by phonenum, type, grp;

【讨论】:

  • 非常感谢您的回答!这似乎可行!您介意帮我解释一下吗?
  • 您好。我发现我没有准确列出所有情况,这导致您的方法在某些情况下无法获得预期的结果。我已经更新了主题。你能帮我再看一遍吗?
  • @orangeChu 。 . .我认为修改后的解决方案应该可行。
  • 谢谢。 emmmm……第九行和第十行和phoneNum一样,但是因为created的不同,不应该放在一起。我发现您的方法将其分为一组。
  • @orangeChu 。 . .你的问题中没有解释。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-23
  • 2019-09-23
  • 2015-09-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多