{"slug":"dividend-income-tracker-with-sql","qid":"yield_on_cost","label":"Yield on cost against current yield, per position","post_title":"Build a Dividend Income Tracker With SQL","post_url":"/blog/dividend-income-tracker-with-sql#q-yield_on_cost","columns":["ticker","yield_on_cost_pct","current_yield_pct"],"rows":[{"ticker":"O","yield_on_cost_pct":5.27,"current_yield_pct":6.11},{"ticker":"XOM","yield_on_cost_pct":4.28,"current_yield_pct":2.46},{"ticker":"KO","yield_on_cost_pct":3.92,"current_yield_pct":2.46},{"ticker":"JNJ","yield_on_cost_pct":3.45,"current_yield_pct":2.08},{"ticker":"PG","yield_on_cost_pct":3.08,"current_yield_pct":2.94},{"ticker":"MSFT","yield_on_cost_pct":1.46,"current_yield_pct":0.74}],"shape":"ranking","sql":"WITH holdings AS\n(\n    SELECT\n        tupleElement(h, 1) AS ticker,\n        tupleElement(h, 2) AS cost_per_share\n    FROM\n    (\n        SELECT arrayJoin([\n            ('KO',    54.10),\n            ('PG',   141.25),\n            ('JNJ',  155.40),\n            ('MSFT', 268.75),\n            ('XOM',   96.20),\n            ('O',     61.85)\n        ]) AS h\n    )\n),\ndeclared AS\n(\n    SELECT\n        ticker,\n        argMax(cash_amount, ex_dividend_date) AS cash_per_payment,\n        argMax(frequency, ex_dividend_date)   AS pays_per_year\n    FROM global_markets.stocks_dividends\n    WHERE ticker IN ('KO', 'PG', 'JNJ', 'MSFT', 'XOM', 'O')\n      AND currency = 'USD'\n      AND frequency IN (1, 2, 4, 12)\n      AND ex_dividend_date >= today() - 400\n      AND ex_dividend_date <= today() + 120\n    GROUP BY ticker\n),\nlast_px AS\n(\n    SELECT\n        ticker,\n        argMax(toFloat64(close), date) AS last_close\n    FROM global_markets.stocks_daily_aggs\n    WHERE ticker IN ('KO', 'PG', 'JNJ', 'MSFT', 'XOM', 'O')\n      AND date >= today() - 45\n    GROUP BY ticker\n)\nSELECT\n    h.ticker AS ticker,\n    round(toFloat64(d.cash_per_payment) * d.pays_per_year / h.cost_per_share * 100, 2) AS yield_on_cost_pct,\n    round(toFloat64(d.cash_per_payment) * d.pays_per_year / p.last_close * 100, 2)     AS current_yield_pct\nFROM holdings AS h\nINNER JOIN declared AS d ON d.ticker = h.ticker\nINNER JOIN last_px  AS p ON p.ticker = h.ticker\nORDER BY yield_on_cost_pct DESC","computed_at":"2026-10-08T16:11:58.257652+00:00","elapsed":0.138539616}