---
title: "Smart Building Analytics: Occupancy & Energy "
description: "Learn how smart building analytics turns raw BMS telemetry into occupancy, energy, and HVAC insight, including a real anomaly-detection SQL pattern. "
section: "Postgres for IoT"
---

> **TimescaleDB is now Tiger Data.**

A building management system captures the raw telemetry: HVAC setpoints, occupancy counts, submeter readings, damper positions, alarm states. A facilities team staring at that stream still can't answer which of 40 buildings wasted the most energy last month, or which floor has run at 20% occupancy for six months. Answering that takes a layer that queries, aggregates, and scores the telemetry a BMS already produces. That's smart building analytics, a different problem than storing the data.

This piece assumes storage and schema are already settled. If you haven't worked through BACnet and Modbus, the narrow-row schema, or a first hypertable and continuous aggregate, start with the [<u>building management system database guide</u>](https://www.tigerdata.com/learn/building-management-system-database) and come back here. This page picks up where storage ends: occupancy, energy, and HVAC analytics, a real anomaly-detection query pattern, and the portfolio-level KPI dashboards a single continuous aggregate can't support.

**Quick answer:** A BMS or BAS controls a building's equipment in real time: setpoints, schedules, alarms. Smart building analytics is a separate layer that turns the resulting telemetry into decisions: occupancy patterns by floor, energy benchmarks across a portfolio, equipment faults before they become work orders, and KPIs a facilities team can act on. The two are complementary, not substitutes.

Tiger Data makes a Postgres-based time-series database, so this piece naturally leans toward that answer. The goal is an honest, engineering-first explanation of what the analytics layer needs to do, not a sales pitch.

## The BMS/analytics split: "controls the building" vs. "understands how it's performing"

Building-analytics vendor CopperTree Analytics puts the distinction well: a BAS or BMS "controls the building," while analytics "understands how the building is performing." Teams often treat a BMS dashboard and an analytics dashboard as competing tools, when they're two layers of the same system. The BMS operates equipment against setpoints and schedules; analytics turns the resulting history into a decision a human has to make: consolidate this floor, replace that chiller, flag this sensor as drifting.

This piece covers the three domains a facilities or operations team asks about most: occupancy, energy, and HVAC efficiency, each fundamentally a query and aggregation problem on top of data the BMS is already producing, not a reason to stand up new infrastructure.

None of this requires a second database. The same Postgres instance storing raw BMS telemetry, running TimescaleDB as the extension that turns it into hypertables, can serve the rollups, KPIs, and anomaly queries below, with no separate analytics warehouse to build and keep in sync.

## Occupancy analytics: from raw sensor counts to space utilization

Occupancy analytics computes a small set of things repeatedly: utilization rate by floor or zone over time, peak-versus-off-peak patterns, and identification of space that's consistently underused relative to capacity.

The underlying pattern is a time-bucketed rollup grouped by zone or floor. That's a query concern, not a storage one; the schema for occupancy counts, motion events, or badge swipes was already covered on the [<u>Building Management System Database</u>](https://www.tigerdata.com/learn/building-management-system-database) webpage. What changes is what you compute on top of it: instead of "how many people are in Zone 3 right now," the question becomes "what fraction of business hours was Zone 3 above 50% capacity this quarter."

Occupancy data is noisier than a raw feed suggests. Motion sensors fire on movement, not headcount; weekends and holidays distort raw averages if not flagged; partial-day patterns, like a floor that fills at 10am and empties by 3pm, get washed out by a bucket that's too coarse or too fine. The right time bucket, typically hourly for operational detail and daily or weekly for reporting, smooths over that noise without hiding the pattern that matters.

Space utilization data is what lets a portfolio operator make a defensible case for consolidating two half-empty floors, or right-sizing a lease renewal, instead of guessing.

## Energy analytics: benchmarking and normalization across a portfolio

A single building's raw kilowatt-hour number tells you almost nothing on its own. Energy analytics starts at the next step: portfolio-level benchmarking, comparing consumption across sites fairly.

The idea that separates a useful benchmark from a misleading one is normalization. A building that used less energy during a mild, low-occupancy month isn't necessarily performing better than one that used more during a heat wave at full occupancy. Weather- and occupancy-normalized consumption accounts for both before ranking sites, so the benchmark reflects operational performance rather than which building had an easier month.

[<u>ApexAnalytica</u>](https://www.tigerdata.com/blog/how-apexanalytica-runs-building-telemetry-transactional-data-rag-on-single-postgres-instance), an AI-powered building intelligence platform, runs exactly this kind of hourly energy rollup across dozens of live sites for portfolio-wide reporting. The [<u>BMS webpage</u>](https://www.tigerdata.com/learn/building-management-system-database) covers how it structures that storage layer; this piece focuses on what's built on top of it.

Keep energy analytics in perspective. Maintenance makes up a substantial share of the same operating budget alongside energy costs, per industry buyer-evaluation research, a reason to treat energy as one input alongside occupancy and HVAC/FDD, not the entire case for an analytics layer.

## HVAC efficiency and fault detection & diagnostics (FDD)

Fault detection and diagnostics flags specific, recognizable failure modes: simultaneous heating and cooling calls on the same air handler (a valve stuck in the wrong position), short-cycling equipment (a compressor or fan cycling far more often than its duty cycle allows), and sensor drift (a reading that slowly diverges from reality until a room feels wrong).

[<u>ASHRAE Guideline 36</u>](https://www.ashrae.org/professional-development/all-instructor-led-training/catalog-of-instructor-led-training/guideline-36-a-brief-introduction) is the industry standard for HVAC control sequencing and fault detection that serious platforms build to, a useful reference point for judging how rigorous a given FDD approach is.

Monitoring frequency matters more than it might seem. An interval that's too coarse, such as 15-minute smart-meter data, can miss short-cycling and similar fast-developing faults entirely, because the fault resolves within the gap between readings. Diagnostics like this need higher-frequency data than a monthly energy read provides.

[<u>Soundsensing</u>](https://www.tigerdata.com/case-studies/soundsensing), an AI-and-sensor-based predictive maintenance platform for HVAC units in commercial real estate, built on the same query-over-telemetry pattern as the previously mentioned use case, applied to equipment health rather than occupancy or energy.

## Anomaly detection: a real query pattern

The common objection is that anomaly detection requires a full machine-learning platform before it's worth doing. It doesn't. A lightweight statistical check, flagging hourly readings that fall more than a few standard deviations from a rolling baseline, is a real, working starting point that catches a meaningful share of operational anomalies.

ApexAnalytica's production pattern combines a statistical anomaly count and a model-based anomaly count in the same join against an hourly energy rollup, returning one combined anomaly count per hour, the practical middle ground between no anomaly detection and a full MLOps pipeline.

Here's a simplified, illustrative version of the statistical half, simply a starting point to adapt (not a drop-in production query):

`WITH baseline AS (
  SELECT
    bucket,
    building_id,
    kwh,
    avg(kwh) OVER (
      PARTITION BY building_id
      ORDER BY bucket
      ROWS BETWEEN 24 PRECEDING AND 1 PRECEDING
    ) AS rolling_avg,
    stddev(kwh) OVER (
      PARTITION BY building_id
      ORDER BY bucket
      ROWS BETWEEN 24 PRECEDING AND 1 PRECEDING
    ) AS rolling_stddev
  FROM energy_hourly
)
SELECT
  bucket,
  building_id,
  kwh,
  round(rolling_avg::numeric, 2) AS baseline_kwh,
  round(rolling_stddev::numeric, 2) AS baseline_stddev
FROM baseline
WHERE kwh > rolling_avg + (3 * rolling_stddev)
ORDER BY bucket DESC;`

This flags any hour where consumption jumped more than three standard deviations above its trailing 24-hour baseline, per building. It's deliberately generic: swap in your own window or threshold, or add a second CTE with a model-based score and join the two the way ApexAnalytica's production query does.

Once you're flagging anomalies, [<u>IPMVP</u>](https://evo-world.org/en/products-services-mainmenu-en/protocols/ipmvp) (the International Performance Measurement and Verification Protocol) is the standard for validating that a detected anomaly, and the savings from fixing it, is measured consistently.

## Building portfolio KPIs and dashboards: beyond one hourly rollup

The [<u>BMS webpage’s</u>](https://www.tigerdata.com/learn/building-management-system-database) schema section showed one hourly continuous aggregate. A real smart building dashboard at portfolio scale needs more: hourly detail for operations, daily and monthly rollups for benchmarking.

Hierarchical continuous aggregates are the mechanism. In [<u>TimescaleDB</u>](https://www.tigerdata.com/docs/learn/continuous-aggregates/hierarchical-continuous-aggregates), you build a continuous aggregate on top of another instead of the raw hypertable: a daily rollup on the hourly one, a monthly rollup on the daily one. Each layer refreshes cheaply from the one below it, reusing calculations already done instead of re-scanning raw data. Each rollup's aggregated rows land in a [<u>materialized hypertable</u>](https://www.tigerdata.com/docs/learn/continuous-aggregates/materialized-hypertables), so it scales and compresses like any other hypertable.

`CREATE MATERIALIZED VIEW energy_daily
WITH (timescaledb.continuous) AS
SELECT
  building_id,
  time_bucket('1 day', bucket) AS day,
  avg(avg_kwh) AS avg_kwh,
  max(max_kwh) AS max_kwh
FROM energy_hourly
GROUP BY building_id, time_bucket('1 day', bucket);

SELECT add_continuous_aggregate_policy('energy_daily',
  start_offset => INTERVAL '3 days',
  end_offset => INTERVAL '1 day',
  schedule_interval => INTERVAL '1 day');`

A monthly rollup stacks on the daily one the same way. One restriction to know: you can't stack a fixed-width bucket on a variable-width one, but a calendar month on a fixed-width daily aggregate works fine.

`CREATE MATERIALIZED VIEW energy_monthly
WITH (timescaledb.continuous) AS
SELECT
  building_id,
  time_bucket('1 month', day) AS month,
  avg(avg_kwh) AS avg_kwh,
  max(max_kwh) AS max_kwh
FROM energy_daily
GROUP BY building_id, time_bucket('1 month', day);

SELECT add_continuous_aggregate_policy('energy_monthly',
  start_offset => INTERVAL '3 months',
  end_offset => INTERVAL '1 day',
  schedule_interval => INTERVAL '1 day');`

Refresh policy is the lever for freshness, not a fixed rule. An occupancy dashboard checked all day wants a short `schedule_interval`; a monthly benchmarking report finance reviews once a period doesn't. Set each level's [<u>refresh policy</u>](https://www.tigerdata.com/docs/build/continuous-aggregates/refresh-policies) to match who's looking and how often.

Compression is new territory past the pillar, which only compressed raw chunks. A continuous aggregate can go cold the same way: once a rollup stops being actively refreshed for a range, it's a candidate for the columnstore, via `add_columnstore_policy`, or by setting `compress_after_refresh` on the refresh-policy job so newly refreshed chunks convert automatically:

`ALTER MATERIALIZED VIEW energy_monthly SET (
  timescaledb.enable_columnstore = true
);

CALL add_columnstore_policy(
  'energy_monthly',
  after => INTERVAL '4 months'
);`

Keep the columnstore after interval larger than the refresh policy’s start_offset, so the policy never compresses a range that’s still being actively refreshed. See [<u>compression on continuous aggregates</u>](https://www.tigerdata.com/docs/build/continuous-aggregates/compression-on-continuous-aggregates) for the full sequencing rules.

If you already have `bms_hourly` or a similar single rollup from the pillar's example, this is additive: layer a daily and monthly aggregate on top of it without touching ingestion.

## Decision framework: which analytics layer should you build first?

Most teams can't build occupancy, energy, and HVAC/FDD analytics at once. Here's how to pick a starting point.

### Start with occupancy analytics if:

- Space planning or right-sizing drives the need, and occupancy data already flows into your BMS.
- You want a fast, low-complexity win: a single rollup grouped by zone is enough.

### Start with energy analytics if:

- Cost reduction and portfolio benchmarking drive the need, across more than one site where a normalized comparison matters.
- Energy rollups are also the most common base for the anomaly-detection pattern above.

### Start with HVAC efficiency and FDD if:

- Equipment reliability or comfort complaints are the pain point, you have higher-frequency HVAC data rather than monthly meter reads, and you're ready to invest in anomaly detection first.

### Invest in hierarchical continuous aggregates now if:

- You manage more than a handful of buildings and need daily and monthly reporting on top of hourly detail, or dashboard freshness differs by audience.

### A single continuous aggregate is probably enough if:

- You manage one building or a few sites with no cross-portfolio reporting need, and one hourly rollup already answers your questions.

## What this looks like in production

[<u>ApexAnalytica</u>](https://www.tigerdata.com/blog/how-apexanalytica-runs-building-telemetry-transactional-data-rag-on-single-postgres-instance) is worth a closer look on the analytics-layer side. The platform runs Ask Apex, an AI agent built on pgvector in the same Postgres instance that stores the building telemetry, reasoning over building documentation and live telemetry together, pairing an analytics and AI layer with the underlying data in one database instead of a separate stack.

ApexAnalytica's stated roadmap includes evaluating continuous aggregates with incremental refresh policies to replace a custom refresh service, and columnstore compression on cold chunks, both the kind of "go deeper than one hourly rollup" work described above. The platform also states it targets ASHRAE Guideline 36-aligned fault detection and IPMVP-compliant measurement and verification, the same two standards referenced earlier.

## Related reading

If you arrived without the storage and schema fundamentals, start with the [<u>building management system database guide</u>](https://www.tigerdata.com/learn/building-management-system-database) for BACnet and Modbus, the narrow-row schema, and a first continuous aggregate.

For the same rollup-and-benchmark pattern applied to grid and utility data, see [<u>Tiger Data's energy and utilities time-series use cases</u>](https://www.tigerdata.com/energy-utilities). For the same pattern applied to a different vertical, the [<u>fleet telemetry database guide</u>](https://www.tigerdata.com/learn/fleet-telemetry-database) covers vehicle sensor data at scale. For implementation detail on building a dashboard on top of a rollup like the ones here, see the [<u>guide to setting up a real-time energy data analytics dashboard</u>](https://www.tigerdata.com/blog/how-to-set-up-a-dashboard-for-global-energy-data-analytics-real-world-use-case).

A companion piece on building energy management system databases is planned as a further follow-up, going deeper into energy-specific reporting than this guide covers.