Valuein
SQL Cookbook

DuckDB + Parquet recipes for Valuein

7 query patterns for the questions analysts and quants ask first. Each one runs as written on the free sample, through the Python SDK or in plain DuckDB. Change the ticker and run.

Before you start

The recipes use table names (fact, "references", …). With the Python SDK those tables are already views, so a recipe runs unchanged in client.run_query(). In plain DuckDB, download the files from the Bulk Data API and create one view per table.

with_sdk.pypython
from valuein_sdk import ValueinClient sql = """SELECT symbol, name FROM "references" WHERE is_active LIMIT 5;"""  # or any recipe below with ValueinClient() as client:  # no key: the free sample    print(client.run_query(sql))  # every table is already a view: no setup
setup.sqlsql
-- Plain DuckDB: download each table once. The sample tier needs no token:--   curl -o fact.parquet https://data.valuein.biz/v1/sample/fact-- then give each file a view named after its table, so the recipes run as written.CREATE VIEW fact             AS SELECT * FROM read_parquet('fact.parquet');CREATE VIEW "references"     AS SELECT * FROM read_parquet('references.parquet');CREATE VIEW index_membership AS SELECT * FROM read_parquet('index_membership.parquet');
01

Start every cross-company query with `references`

`references` is entity joined to security: one row per listing with `cik`, `symbol`, `name`, `sector`. Filter `is_active AND is_primary_ticker` for one row per company today.

Why this works ↓

`references` saves you joining `entity` and `security` yourself. A company can have several rows (share classes, retired tickers), so `is_active` keeps tickers in use today and `is_primary_ticker` keeps one per company. Index membership lives in `index_membership`, keyed on `cik`; there is no `is_sp500` flag. `references` is a reserved word in DuckDB, so always quote it.

sql
SELECT  r.symbol,  r.name,  r.sector,  r.industryFROM "references" rJOIN index_membership im  ON im.cik = r.cikWHERE im.index_name = 'SP500'  AND im.removal_date IS NULL  -- current member  AND r.is_active               -- a ticker in use today  AND r.is_primary_ticker       -- one row per companyORDER BY r.sector, r.symbol;

Note · Use this as the spine of any screen, peer search or universe.

02

Latest annual value per company with LATERAL

A LATERAL subquery picks one row per company. `fact` keys on `entity_id`, which equals `references.cik`; it has no ticker column.

Why this works ↓

Pulling every row and deduplicating in pandas is slow and easy to get wrong. LATERAL runs the inner query once per company and stops at LIMIT 1. Sorting by `period_end` then `accepted_at` takes the latest period and, within it, the latest filed value.

sql
WITH members AS (  SELECT r.cik, r.symbol, r.sector  FROM "references" r  JOIN index_membership im    ON im.cik = r.cik  WHERE im.index_name = 'SP500'    AND im.removal_date IS NULL    AND r.is_active    AND r.is_primary_ticker)SELECT  m.symbol,  m.sector,  f.period_end,  f.numeric_value AS revenueFROM members m,LATERAL (  SELECT f0.period_end, f0.numeric_value  FROM fact f0  WHERE f0.entity_id        = m.cik    AND f0.standard_concept = 'TotalRevenue'    AND f0.fiscal_period    = 'FY'  ORDER BY f0.period_end DESC, f0.accepted_at DESC  LIMIT 1) fORDER BY revenue DESC NULLS LASTLIMIT 25;

Note · LATERAL is much cheaper than a self-join on `fact`.

03

Pivot several concepts in one pass over `fact`

Deduplicate vintages first, then one MAX(CASE) pivot turns revenue, net income, EPS and operating cash flow into columns. Group by `period_end`.

Why this works ↓

A 10-K repeats two or three earlier years as comparatives, so one period can appear in several filings. QUALIFY keeps the latest-filed value per (company, concept, period); without it MAX() would pick whichever vintage is largest. The pivot then reads `fact` once instead of once per concept.

sql
WITH ids AS (  SELECT cik, symbol  FROM "references"  WHERE symbol IN ('AAPL', 'MSFT', 'GOOGL', 'NVDA')    AND is_active    AND is_primary_ticker),latest AS (  -- A 10-K repeats earlier years as comparatives: keep the  -- latest-filed value for each (company, concept, period).  SELECT fa.entity_id, fa.period_end, fa.standard_concept, fa.numeric_value  FROM fact fa  JOIN ids ON ids.cik = fa.entity_id  WHERE fa.fiscal_period = 'FY'    AND fa.standard_concept IN ('TotalRevenue', 'NetIncome', 'EPSDiluted', 'OperatingCashFlow')  QUALIFY ROW_NUMBER() OVER (    PARTITION BY fa.entity_id, fa.standard_concept, fa.period_end    ORDER BY fa.accepted_at DESC  ) = 1)SELECT  ids.symbol,  l.period_end,  MAX(CASE WHEN l.standard_concept = 'TotalRevenue'      THEN l.numeric_value END) AS revenue,  MAX(CASE WHEN l.standard_concept = 'NetIncome'         THEN l.numeric_value END) AS net_income,  MAX(CASE WHEN l.standard_concept = 'EPSDiluted'        THEN l.numeric_value END) AS eps_diluted,  MAX(CASE WHEN l.standard_concept = 'OperatingCashFlow' THEN l.numeric_value END) AS operating_cash_flowFROM latest lJOIN ids ON ids.cik = l.entity_idGROUP BY ids.symbol, l.period_endORDER BY ids.symbol, l.period_end;

Note · Each extra concept costs one more CASE, not one more scan.

04

Keep the latest vintage with QUALIFY ROW_NUMBER()

QUALIFY ROW_NUMBER() keeps one row per period: the most recently accepted value. `value_as_filed` and `restated` show what changed since the first filing.

Why this works ↓

Every filing that reports a period adds a row; nothing is overwritten. QUALIFY is the cleanest way to keep the latest one. `numeric_value` is the value in that filing, `value_as_filed` the value first reported for the period, and `restated` is true when they differ.

sql
WITH tsla AS (  SELECT cik FROM "references"  WHERE symbol = 'TSLA' AND is_active AND is_primary_ticker)SELECT  fa.period_end,  fa.fiscal_period,  fa.numeric_value,  fa.value_as_filed,  fa.restated,  fa.accepted_atFROM fact faJOIN tsla ON tsla.cik = fa.entity_idWHERE fa.standard_concept = 'NetIncome'QUALIFY ROW_NUMBER() OVER (  PARTITION BY fa.entity_id, fa.period_end, fa.fiscal_period  ORDER BY fa.accepted_at DESC) = 1ORDER BY fa.period_end DESC, fa.fiscal_period;
As reported vs restatedFY2020, $M. A point-in-time query returns the figure as it was first reported.
Metricas reportedrestated
Revenue10,38810,388
Operating income2,1141,902
Net income1,6401,431
Diluted EPS3.052.66

verify_fact_lineage() → both versions retained · each keyed to its filing

Note · Drop the QUALIFY clause to see every vintage of each period.

05

Quarter-only cash flow, Q4 included

Most Q2 and Q3 cash-flow rows are year-to-date as filed. `derived_quarterly_value` holds the quarter-only figure; on the FY row it is Q4.

Why this works ↓

Companies usually report cash flow year-to-date in their 10-Qs, and there is no Q4 10-Q at all. The pipeline stores the quarter-only figure in `derived_quarterly_value`: equal to the filed value for a standalone quarter, the year-to-date difference otherwise, and on the FY row, Q4 (the year minus the first three quarters). `is_cumulative` tells you which rows were filed year-to-date.

sql
WITH aapl AS (  SELECT cik FROM "references"  WHERE symbol = 'AAPL' AND is_active AND is_primary_ticker)SELECT  fa.period_end,  fa.fiscal_period,  fa.is_cumulative,                                      -- TRUE = year-to-date as filed  fa.numeric_value                                       AS as_filed,  COALESCE(fa.derived_quarterly_value, fa.numeric_value) AS quarter_onlyFROM fact faJOIN aapl ON aapl.cik = fa.entity_idWHERE fa.standard_concept = 'OperatingCashFlow'  AND fa.fiscal_period IN ('Q1', 'Q2', 'Q3', 'FY')       -- FY row carries Q4  AND (fa.fiscal_period <> 'FY' OR fa.derived_quarterly_value IS NOT NULL)QUALIFY ROW_NUMBER() OVER (  PARTITION BY fa.period_end, fa.fiscal_period  ORDER BY fa.accepted_at DESC) = 1ORDER BY fa.period_end;

Note · COALESCE falls back to `numeric_value` for a standalone quarter. An FY row is kept only when it carries Q4, so a full-year total never poses as a quarter.

06

Point-in-time screen: the universe and the data on a date

Filter `index_membership` by its effective and removal dates and `fact` by `accepted_at`, so both the company list and its numbers are what was known on that date.

Why this works ↓

A backtest needs the index as it stood on the trade date, not today's members, and only the numbers already filed. Membership windows are half-open: a company removed on a date is not a member on it. With the Python SDK you can also pass `ValueinClient(as_of=...)`, which applies the `accepted_at` filter to every point-in-time table for you.

sql
WITH universe_at AS (  -- S&P 500 members on 2024-01-02. Removal is exclusive:  -- a company removed on that date is no longer a member.  SELECT DISTINCT im.cik  FROM index_membership im  WHERE im.index_name = 'SP500'    AND im.effective_date <= DATE '2024-01-02'    AND (im.removal_date IS NULL OR im.removal_date > DATE '2024-01-02')),known AS (  -- Fiscal years that ended in 2022, using only values the SEC had  -- accepted before 2024-01-02 (later restatements are ignored).  SELECT fa.entity_id, fa.standard_concept, fa.numeric_value  FROM fact fa  WHERE fa.accepted_at < TIMESTAMP '2024-01-02 00:00:00'    AND fa.fiscal_period = 'FY'    AND fa.period_end BETWEEN DATE '2022-01-01' AND DATE '2022-12-31'    AND fa.standard_concept IN ('TotalRevenue', 'NetIncome')  QUALIFY ROW_NUMBER() OVER (    PARTITION BY fa.entity_id, fa.standard_concept    ORDER BY fa.accepted_at DESC  ) = 1)SELECT  u.cik,  MAX(CASE WHEN k.standard_concept = 'TotalRevenue' THEN k.numeric_value END) AS revenue,  MAX(CASE WHEN k.standard_concept = 'NetIncome'    THEN k.numeric_value END) AS net_income,  net_income / NULLIF(revenue, 0)                                              AS net_marginFROM universe_at uJOIN known k ON k.entity_id = u.cikGROUP BY u.cikORDER BY revenue DESC NULLS LASTLIMIT 50;
Delisted companies stay inBankrupt, acquired, failed or taken private: kept on Pro and Institutional.
  1. Enron Corp

    ENRNQ

    bankrupt2001

  2. Lehman Brothers

    LEH

    bankrupt2008

  3. Bear Stearns

    BSC

    acquired2008

  4. Countrywide Financial

    CFC

    acquired2008

  5. Blockbuster Inc

    BLOAQ

    bankrupt2010

  6. Whole Foods

    WFM

    acquired2017

  7. Sears Holdings

    SHLD

    bankrupt2018

  8. Twitter Inc

    TWTR

    taken private2022

  9. SVB Financial

    SIVB

    failed2023

get_pit_universe(date) returns the market as it stood on that date, not as it survived.

Note · The membership filter prevents survivorship bias; the accepted_at filter prevents look-ahead bias. Join `references` on `cik` for today's ticker.

07

Defensive ratio math: ABS and NULLIF

Wrap capex in ABS (filers disagree on its sign) and every divisor in NULLIF (a zero divisor becomes NULL instead of an error).

Why this works ↓

Some filers report capex as a negative cash flow and some as a positive amount, and some periods have zero revenue. ABS and NULLIF make the formula safe for all of them.

sql
WITH ids AS (  SELECT cik, symbol  FROM "references"  WHERE symbol IN ('AAPL', 'MSFT', 'GOOGL', 'META', 'WMT', 'COST')    AND is_active    AND is_primary_ticker),latest AS (  SELECT fa.entity_id, fa.standard_concept, fa.numeric_value  FROM fact fa  JOIN ids ON ids.cik = fa.entity_id  WHERE fa.fiscal_period = 'FY'    AND fa.standard_concept IN ('TotalRevenue', 'OperatingCashFlow', 'CAPEX')  QUALIFY ROW_NUMBER() OVER (    PARTITION BY fa.entity_id, fa.standard_concept    ORDER BY fa.period_end DESC, fa.accepted_at DESC  ) = 1),pivoted AS (  SELECT    ids.symbol,    MAX(CASE WHEN l.standard_concept = 'TotalRevenue'      THEN l.numeric_value END) AS revenue,    MAX(CASE WHEN l.standard_concept = 'OperatingCashFlow' THEN l.numeric_value END) AS ocf,    MAX(CASE WHEN l.standard_concept = 'CAPEX'             THEN l.numeric_value END) AS capex  FROM latest l  JOIN ids ON ids.cik = l.entity_id  GROUP BY ids.symbol)SELECT  symbol,  ocf,  capex,  -- ABS: filers disagree on the sign of capex.  -- NULLIF: a zero divisor returns NULL instead of failing the row.  ocf - ABS(capex)                        AS free_cash_flow,  (ocf - ABS(capex)) / NULLIF(revenue, 0) AS fcf_marginFROM pivotedORDER BY fcf_margin DESC NULLS LAST;

Note · A missing input yields NULL rather than a wrong number; check the inputs when a ratio is NULL.

More patterns?

The Python SDK ships named SQL templates for common workflows: fundamentals by ticker, margins, free cash flow, factor screens, peer comparisons, filing links. client.list_templates() lists them all.