Dividend Analysis and Total Return
Dividend Analysis and Total Return
Dividends are cash payments made by companies to shareholders, typically quarterly. For long-term investors, dividends are a crucial component of total return — a stock yielding 3% annually adds meaningful income on top of price appreciation. Understanding dividend analysis in SQL is essential for income-focused investment portfolios.
Key Dividend Concepts
Before writing queries, understand the terminology:
- Dividend Yield: Annual dividend / Stock price. A stock at $100 paying $3/year has a 3% yield
- Ex-Dividend Date: You must own the stock before this date to receive the dividend
- Payment Date: The date the cash actually arrives in your account
- Payout Ratio: Dividends paid / Earnings per share. Above 80% may be unsustainable
- Total Return: Price appreciation PLUS dividends received. Ignoring dividends understates long-term returns for dividend stocks
Step 1 — Dividend Yield by Stock
Yield is computed by dividing the annual dividend per share (or trailing 12-month dividends) by the current stock price. This normalises dividends for comparison across stocks at different price levels.
WITH annual_dividends AS (
SELECT
company_id,
EXTRACT(YEAR FROM ex_date) AS year,
SUM(amount_per_share) AS annual_dividend
FROM dividends
GROUP BY company_id, EXTRACT(YEAR FROM ex_date)
),
latest_price AS (
SELECT DISTINCT ON (company_id) company_id, close_price AS current_price
FROM stock_prices
ORDER BY company_id, price_date DESC
),
yield_calc AS (
SELECT
ad.company_id,
ad.year,
ad.annual_dividend,
lp.current_price,
ROUND(ad.annual_dividend / NULLIF(lp.current_price, 0) * 100, 2) AS dividend_yield_pct
FROM annual_dividends ad
JOIN latest_price lp ON lp.company_id = ad.company_id
)
SELECT
c.ticker, c.name, c.sector,
yc.year,
ROUND(yc.annual_dividend, 4) AS annual_dividend_per_share,
ROUND(yc.current_price, 2) AS current_price,
yc.dividend_yield_pct,
RANK() OVER (ORDER BY yc.dividend_yield_pct DESC) AS yield_rank
FROM yield_calc yc
JOIN companies c ON c.company_id = yc.company_id
WHERE yc.year = EXTRACT(YEAR FROM CURRENT_DATE) - 1 -- prior full year
ORDER BY yc.dividend_yield_pct DESC;
What This Returns
Stocks ranked by dividend yield. High yield (>4%) can indicate attractive income or, alternatively, that the market expects a dividend cut (the price has fallen more than the dividend, inflating the yield). DISTINCT ON (company_id) ORDER BY price_date DESC fetches the most recent price for each company — the PostgreSQL-idiomatic "latest row per group" pattern.