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

基于PostgreSQL按天存储的property_calendars表计算入住率

没问题,我来帮你搞定PostgreSQL里计算物业入住率的需求!结合你给出的property_calendars表结构(按天存储单条记录),我会分几种常见场景给出SQL方案,你可以根据实际需求调整。

核心逻辑说明

入住率的常规定义是:

入住率 = (已预订天数 / 统计周期内的有效天数) × 100%
这里的「有效天数」可以是周期内的总天数,也可以是物业可售天数(排除维护、不可用等状态),下面的示例会分别覆盖这两种情况。


场景1:单个物业指定时间段的入住率(按表中记录的天数计算)

如果你的表中已经完整存储了目标周期内的所有日期记录(每天一行),可以直接用这个查询:

SELECT
  property_id,
  COUNT(*) FILTER (WHERE status = 'booked') AS booked_days,
  COUNT(*) AS total_days_in_period,
  ROUND(
    (COUNT(*) FILTER (WHERE status = 'booked')::NUMERIC / COUNT(*)) * 100,
    2
  ) AS occupancy_rate_percent
FROM property_calendars
WHERE
  property_id = 56 -- 替换为你要查询的物业ID
  AND date BETWEEN '2017-10-01' AND '2017-10-31' -- 替换为目标统计周期
GROUP BY property_id;
  • COUNT(*) FILTER (WHERE status = 'booked'):精准统计该物业在周期内的已预订天数
  • 转换为NUMERIC是为了避免PostgreSQL的整数除法(如果用整数计算会直接取整,丢失精度)
  • ROUND(..., 2)用来把百分比保留两位小数,看起来更直观

场景2:单个物业指定时间段的入住率(按实际日历天数计算)

如果你的表中可能存在日期缺失(比如物业刚上线,之前的日期没有记录),这时候用实际日历天数作为基数更准确:

WITH date_range AS (
  -- 生成目标周期内的所有日期
  SELECT generate_series(
    '2017-10-01'::DATE,
    '2017-10-31'::DATE,
    '1 day'::INTERVAL
  )::DATE AS date
),
property_full_days AS (
  -- 左连接日历表,补全缺失的日期记录
  SELECT
    dr.date,
    pc.status
  FROM date_range dr
  LEFT JOIN property_calendars pc
    ON dr.date = pc.date AND pc.property_id = 56
)
SELECT
  56 AS property_id,
  COUNT(*) FILTER (WHERE status = 'booked') AS booked_days,
  COUNT(*) AS total_days_in_period, -- 这里就是周期的实际总天数
  ROUND(
    (COUNT(*) FILTER (WHERE status = 'booked')::NUMERIC / COUNT(*)) * 100,
    2
  ) AS occupancy_rate_percent
FROM property_full_days;

这个方案用CTE生成了完整的日期序列,确保即使某天没有记录,也会被纳入统计,结果更贴合真实的日历周期。


场景3:按物业+月份分组统计入住率

如果需要批量统计多个物业在不同月份的入住率,可以用DATE_TRUNC来按月份分组:

SELECT
  property_id,
  DATE_TRUNC('month', date)::DATE AS month_start, -- 显示每个月的第一天
  COUNT(*) FILTER (WHERE status = 'booked') AS booked_days,
  COUNT(*) AS total_days_in_month,
  ROUND(
    (COUNT(*) FILTER (WHERE status = 'booked')::NUMERIC / COUNT(*)) * 100,
    2
  ) AS occupancy_rate_percent
FROM property_calendars
WHERE date >= '2017-01-01' AND date < '2018-01-01' -- 统计2017年全年
GROUP BY property_id, DATE_TRUNC('month', date)
ORDER BY property_id, month_start;

场景4:基于「可售天数」计算入住率

如果你的业务中存在不可售状态(比如维护、暂停预订),需要排除这些天数来计算入住率,可以调整查询:

SELECT
  property_id,
  COUNT(*) FILTER (WHERE status = 'booked') AS booked_days,
  COUNT(*) FILTER (WHERE status IN ('booked', 'available')) AS available_days, -- 可售天数:已预订+可预订
  ROUND(
    (COUNT(*) FILTER (WHERE status = 'booked')::NUMERIC / COUNT(*) FILTER (WHERE status IN ('booked', 'available'))) * 100,
    2
  ) AS occupancy_rate_percent
FROM property_calendars
WHERE
  property_id = 56
  AND date BETWEEN '2017-10-01' AND '2017-10-31'
GROUP BY property_id;

这里把「可售天数」定义为status是booked或available的天数,你可以根据实际的状态值修改这个条件。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:50:12