【问题标题】:CREATE a table from a select query with LEAD/LAG使用 LEAD/LAG 从选择查询创建表
【发布时间】:2020-07-15 12:28:26
【问题描述】:

这是我手头的那种桌子:

 SELECT * FROM smf_table LIMIT 20;
   id    | trip_id | segment_id | segment_start_timestamp | timestamp  |     lat     |     lon     | travelmode 
---------+---------+------------+-------------------------+------------+-------------+-------------+------------
 5338113 |  533811 |          3 | 2016-04-01 00:47:16+01  | 1459467971 |  41.1523521 |  -8.6097233 |          0
 5338113 |  533811 |          3 | 2016-04-01 00:47:16+01  | 1459468020 |  41.1523518 |  -8.6097168 |          0
 5338113 |  533811 |          3 | 2016-04-01 00:47:16+01  | 1459468026 |  41.1524153 |  -8.6097054 |          0
 5338113 |  533811 |          3 | 2016-04-01 00:47:16+01  | 1459468031 |  41.1524057 |   -8.609701 |          0
 5338113 |  533811 |          3 | 2016-04-01 00:47:16+01  | 1459468036 |  41.1523647 |  -8.6097146 |          0
 5338113 |  533811 |          3 | 2016-04-01 00:47:16+01  | 1459468041 |  41.1525607 |  -8.6096725 |          0
 5338113 |  533811 |          3 | 2016-04-01 00:47:16+01  | 1459468046 |  41.1525077 |  -8.6096843 |          0
 5338113 |  533811 |          3 | 2016-04-01 00:47:16+01  | 1459468051 |  41.1524966 |  -8.6096833 |          0
 5338151 |  533815 |          1 | 2016-04-01 00:06:40+01  | 1459465282 | 41.14454009 | -8.56292593 |          3
 5338151 |  533815 |          1 | 2016-04-01 00:06:40+01  | 1459465412 |    41.14454 |  -8.5629259 |          3
 5338151 |  533815 |          1 | 2016-04-01 00:06:40+01  | 1459465600 |   41.163172 |  -8.5838214 |          3

这是一个包含超过 1 亿行的大表。我想使用来自smf_table 的过滤结果创建新表temp_table,以便在新表中:

  1. 不包括travelmodeIS NULL 的行(有很多)
  2. 不包括row2_timestamp - row1_timestamp = 0 所在的行。

所以我想到了这样使用子查询:

CREATE TABLE temp_table
AS
WITH cte AS
(SELECT LEAD(timestamp) OVER (PARTITION BY id ORDER BY timestamp) 
  - LAG(timestamp) OVER (PARTITION BY id ORDER BY timestamp) 
FROM smf_table
) 
SELECT id,
  lat,
  lon,
  timestamp,
  travel mode
FROM smf_table
WHERE travelmode IS NOT NULL AND cte !=0;

ERROR:  relation "smf_table" does not exist
LINE 13: FROM smf_table

【问题讨论】:

  • 您可能会从此查询中得到错误,但并不是说smf_table 不存在。您确定在同一个数据库中运行这两个查询吗?
  • 您可能想从 CTE 中进行选择,为该列指定别名,然后也返回其他列。 cte ! = 0 到底是什么意思?

标签: sql postgresql aggregate-functions sql-function


【解决方案1】:

您不应该收到 smf_table 未定义的错误。您可能会遇到其他错误——cte 未定义,CTE 中的列没有名称,travel 未定义。

您需要从 CTE 中进行选择才能使用其中的列。 CTE 类似于表/视图,而不是列:

WITH cte AS (
      SELECT s.*,
             LEAD(timestamp) OVER (PARTITION BY id ORDER BY timestamp) - LAG(timestamp) OVER (PARTITION BY id ORDER BY timestamp) as diff
      FROM smf_table s
     ) 
SELECT id lat, lon, timestamp, travelmode
FROM cte
WHERE travelmode IS NOT NULL AND diff <> 0;

【讨论】:

    【解决方案2】:

    您必须从表中选择所需的列并执行操作,并且在选择最终结果时,您必须从 cte 而不是原始表中进行选择。您也可以直接如下创建表,无需递归查询。

    CREATE TABLE temp_table as
        SELECT SELECT LEAD(timestamp) OVER (PARTITION BY id ORDER BY timestamp) 
      - LAG(timestamp) OVER (PARTITION BY id ORDER BY timestamp) as date_time , id,
      lat,
      lon,
      timestamp,
      travel mode
    FROM smf_table
    WHERE travelmode IS NOT NULL AND cte !=0;
    

    【讨论】:

    • 谢谢,但我在此查询中看不到您对cte 的定义。
    【解决方案3】:

    为什么要从LEAD() 中减去LAG()?您真的是要在忽略当前记录的情况下将后面的记录与前面的记录进行比较吗?

    另外,如果timestamp1 - timestamp2 = 0timestamp1 = timestamp2,所以这可以用group by 解决。

    CREATE TABLE temp_table
    AS
    SELECT id,
           max(lat) as lat,
           max(lon) as lon,
           timestamp,
           max(travelmode) as travelmode
      FROM smf_table
     WHERE travelmode IS NOT NULL 
     GROUP by id, timestamp
    HAVING count(*) = 1 
    

    【讨论】:

    • timestamp1 - timestamp2 = 0 我正在做一个健全性检查,以确保连续行之间的时间差不为零。
    • @arilwan 将lag() 与“lead()”进行比较不会将当前行与其前一行或后一行进行比较。它将下一行与上一行进行比较。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多