Estimate what a query costs before you run it
This recipe tells you what already happened. The analyzer takes a query you have not run yet and estimates what it will scan, in your browser.
Which GCP services changed the most month over month?
Service-level month-over-month movement from the billing export.
Costs money to run, queries your billing export tableReviewed against Google’s docs, 23 Oct 2026
Permissions. Needs read access to the dataset holding your billing export (BigQuery Data Viewer on that dataset); bigquery.jobs.create to run any query (BigQuery Job User has it).
-- Replace the table with your billing export.
-- This scans real data: filter the partition column first. The filter starts
-- a day before the first of the month before last, so both complete invoice
-- months are read in full; a fixed window such as 70 days cuts off the start
-- of the earlier month and makes every service look like it grew.
WITH monthly AS (
SELECT
invoice.month AS invoice_month,
service.description AS service,
SUM(cost) AS cost,
SUM(IFNULL((SELECT SUM(c.amount) FROM UNNEST(credits) c), 0)) AS credits
FROM `PROJECT.DATASET.gcp_billing_export_v1_XXXXXX_XXXXXX_XXXXXX`
WHERE _PARTITIONTIME >= TIMESTAMP(DATE_SUB(
DATE_SUB(DATE_TRUNC(CURRENT_DATE(), MONTH), INTERVAL 2 MONTH), INTERVAL 1 DAY))
GROUP BY invoice_month, service
)
SELECT
service,
ROUND(SUM(IF(invoice_month = FORMAT_DATE('%Y%m', DATE_SUB(CURRENT_DATE(), INTERVAL 2 MONTH)), cost, 0)), 2) AS prior_month,
ROUND(SUM(IF(invoice_month = FORMAT_DATE('%Y%m', DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH)), cost, 0)), 2) AS last_month,
ROUND(
SUM(IF(invoice_month = FORMAT_DATE('%Y%m', DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH)), cost, 0))
- SUM(IF(invoice_month = FORMAT_DATE('%Y%m', DATE_SUB(CURRENT_DATE(), INTERVAL 2 MONTH)), cost, 0)), 2) AS delta,
ROUND(SUM(IF(invoice_month = FORMAT_DATE('%Y%m', DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH)), credits, 0)), 2) AS last_month_credits
FROM monthly
GROUP BY service
ORDER BY ABS(delta) DESC
LIMIT 50;What it returns
- delta
- Last month minus the month before, in your billing currency, before credits.
- last_month_credits
- Committed-use, sustained-use and promotional credits applied last month, as negative amounts.
How to read it
- This tells you what moved, not why. A service can rise because you used more of it or because a discount expired, and those need opposite responses.
- Compare complete invoice months only. A partial current month will always look like a collapse.
- cost is before credits. Credits ride on each row of the export as a nested list of negative amounts, which is why they have their own column here. Decide up front whether you are analyzing gross or net cost and stay consistent.
Take it further
Run this once, or have it run every day.
Finitizer evaluates this class of question continuously against your live BigQuery estate, tracks how each number moves between runs, and turns findings into assigned tasks. Read-only and keyless.
See how Finitizer works