You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL的pl/pgSQL函数改造为Snowflake兼容版本技术咨询

Snowflake兼容版停车时长计算方案

由于当前Snowflake暂不支持PL/pgSQL语法,我们将原有函数改造为Snowflake原生SQL存储过程,完全匹配业务需求:

核心适配调整点

  • 移除PostgreSQL特有nextval语法:durations表已配置autoincrement自增主键,插入时无需显式指定id字段
  • 时间语法适配:用Snowflake原生DATEDIFF计算秒级时长,DATEADD做日期偏移计算
  • 变量优化:提前读取properties配置值减少子查询嵌套,提升执行效率
  • 所有原有业务校验规则完整保留:过滤XX前缀厂商、避免重复写入、动态更新截止日期逻辑完全不变

完整存储过程代码

CREATE OR REPLACE PROCEDURE calculateDuration()
RETURNS VARCHAR
LANGUAGE SQL
AS
$$
DECLARE
  v_limit_date TIMESTAMP;
  v_limit_days INT;
  v_max_event_time TIMESTAMP;
BEGIN
  -- 读取配置参数
  SELECT PROP_VALUE::TIMESTAMP INTO v_limit_date FROM properties WHERE prop_key = 'DURATION.LIMIT.DATE';
  SELECT PROP_VALUE::INT INTO v_limit_days FROM properties WHERE prop_key = 'DURATION.LIMIT.DAYS';

  -- 插入匹配的进出时长记录
  INSERT INTO durations (
    odb_created_at, event_id_arrival, event_id_departure,
    event_time_arrival, event_time_departure,
    card_nr, ticket_type, duration, manufacturer, carpark_id
  )
  WITH cte AS (
    SELECT 
      e.id, e.card_nr, e.event_time, e.ticket_type, e.manufacturer, e.carpark_id, e.device_type,
      ROW_NUMBER() OVER (ORDER BY e.card_nr, e.carpark_id, e.event_time, e.device_type) AS rn
    FROM events e
    LEFT JOIN durations d 
      ON d.event_id_arrival = e.id OR d.event_id_departure = e.id
    WHERE 
      e.event_time >= :v_limit_date
      AND e.device_type IN (1, 2)
      AND e.event_type = 2
      AND e.manufacturer LIKE 'XX%'
      AND d.id IS NULL
  )
  SELECT
    CURRENT_TIMESTAMP(),
    arrived_entry.id,
    departed_entry.id,
    arrived_entry.event_time,
    departed_entry.event_time,
    arrived_entry.card_nr,
    arrived_entry.ticket_type,
    DATEDIFF('second', arrived_entry.event_time, departed_entry.event_time),
    arrived_entry.manufacturer,
    arrived_entry.carpark_id
  FROM (SELECT * FROM cte WHERE device_type = 1) AS arrived_entry
  INNER JOIN (SELECT * FROM cte WHERE device_type = 2) AS departed_entry
    ON arrived_entry.card_nr = departed_entry.card_nr
    AND arrived_entry.carpark_id = departed_entry.carpark_id
    AND arrived_entry.rn + 1 = departed_entry.rn;

  -- 更新配置表的截止日期
  SELECT MAX(event_time) INTO v_max_event_time FROM events WHERE event_time >= :v_limit_date;
  UPDATE properties
  SET PROP_VALUE = DATEADD('day', -1 * :v_limit_days, :v_max_event_time)::VARCHAR
  WHERE PROP_KEY = 'DURATION.LIMIT.DATE';

  RETURN '执行成功,已计算最新停车时长记录';
END;
$$;

使用方法

每日导入事件数据后,执行以下命令即可完成计算:

CALL calculateDuration();

验证说明

你提供的样例数据执行后,会生成5条符合预期的时长记录,不会出现重复写入问题,properties表的DURATION.LIMIT.DATE会自动按规则更新。

内容的提问来源于stack exchange,提问作者Djabone

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 05:45:04