Postgresql根据基于日历的日历表计算占用率

时间:2018-05-03 15:11:02

标签: postgresql

我在postgreSQL数据库中有一个property_calendars表,每个属性都有一个每行结构。这是一个属性的一个月的样本数据为csv:

"id","property_id","status","price","currency","date","note","created_at","updated_at"
30053752,56,"booked",170,"GBP","2017-10-01",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053753,56,"booked",286,"GBP","2017-10-02",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053754,56,"booked",271,"GBP","2017-10-03",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053755,56,"booked",263,"GBP","2017-10-04",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053756,56,"booked",278,"GBP","2017-10-05",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053757,56,"booked",284,"GBP","2017-10-06",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053758,56,"booked",252,"GBP","2017-10-07",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053759,56,"booked",254,"GBP","2017-10-08",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053760,56,"available",247,"GBP","2017-10-09",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053761,56,"booked",170,"GBP","2017-10-10",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053762,56,"booked",170,"GBP","2017-10-11",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053763,56,"booked",170,"GBP","2017-10-12",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053764,56,"booked",170,"GBP","2017-10-13",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053765,56,"booked",170,"GBP","2017-10-14",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053766,56,"booked",170,"GBP","2017-10-15",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053767,56,"booked",170,"GBP","2017-10-16",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053768,56,"unavailable",170,"GBP","2017-10-17",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053769,56,"unavailable",170,"GBP","2017-10-18",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053770,56,"unavailable",170,"GBP","2017-10-19",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053771,56,"booked",170,"GBP","2017-10-20",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053772,56,"booked",170,"GBP","2017-10-21",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053773,56,"booked",170,"GBP","2017-10-22",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053774,56,"booked",170,"GBP","2017-10-23",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053775,56,"booked",170,"GBP","2017-10-24",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053776,56,"booked",170,"GBP","2017-10-25",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053777,56,"booked",170,"GBP","2017-10-26",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053778,56,"booked",170,"GBP","2017-10-27",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053779,56,"booked",170,"GBP","2017-10-28",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053780,56,"available",170,"GBP","2017-10-29",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053781,56,"booked",170,"GBP","2017-10-30",,"2018-04-19 04:04:48","2018-04-19 04:04:48"
30053782,56,"booked",170,"GBP","2017-10-31",,"2018-04-19 04:04:48","2018-04-19 04:04:48"

在这样的桌子上查询给定时间段内的占用情况的最佳方法是什么?在此上下文中计算占用率的公式为:x = (n - u) / n * 100其中

n = total nights 
u = unavailable nights
b = booked nights
x = occupancy

上述数据26 / 31 * 100 = 87.83%当月占用

1 个答案:

答案 0 :(得分:2)

您可以将COUNT与条件一起使用,然后根据您的公式计算占用率(注意:似乎正确的公式为b / (n - u) * 100,它会给出83.87%)。

WITH cte AS
(SELECT
  COUNT(*) n,
  COUNT(CASE WHEN status = 'booked' THEN 1 END) b,
  COUNT(CASE WHEN status = 'unavailable' THEN 1 END) u,
  COUNT(CASE WHEN status = 'available' THEN 1 END) a
FROM
  occupancy
WHERE
  "date" BETWEEN '2017-10-01' AND '2017-10-31')

SELECT 
  n, 
  b, 
  u, 
  a, 
  b * 100.0 / (n - u) occupancy -- the numerator is multiplied by a float 100.0 to avoid integer division
FROM cte

自PostgreSQL 9.4起,您还可以使用COUNT(*) FILTER (...)子句:

SELECT 
  COUNT(*) FILTER (WHERE status = 'booked') b 
  ...
FROM occupancy