Bago ang course na ito: SQL Joins & Analysis (course 7.4.2). Dapat alam mo na ang mga join, LEFT JOIN, GROUP BY na may HAVING, CASE, mga subquery at mga view. Ginagamit ng course na ito ang parehong apat-na-table na shop at ang order_lines view mula sa course na iyon, kaya buuin muna ang mga iyon (course 7.4.2, Lessons 1 at 6). Dito, mas malalim ang tatalakayin natin: window functions, CTE, mga index at query plan.
Bago ka magsimula, at mga CTE: pagpapangalan sa mga hakbang ng query
Kapag nagluluto ka ng malaking handaan, naghahanda ka muna ng maliliit na mangkok: tinadtad na sibuyas, hinugasang bigas, hinalong sarsa. May pangalan ang bawat mangkok. Tapos pagsasamahin mo. Ang CTE ay maliit na mangkok na may pangalan sa loob ng isang query.
- Ang CTE (common table expression) ay isang SELECT na may pangalan, nakasulat sa itaas ng query gamit ang
WITH name AS (...). Magagamit na ng pangunahing query angnamena parang table. - Puwede kang magsulat ng ilang CTE sa isang WITH, pinaghihiwalay ng kuwit. Magagamit ng sumunod na CTE ang nauna.
- Umiiral lang ang CTE habang tumatakbo ang isang query na iyon. Ang view (course 7.4.2) ay naka-save sa database; ang CTE ay hindi.
- Ginagawang nababasa ng mga CTE ang mahahabang query: may pangalan ang bawat hakbang at masusubukan mo ang bawat hakbang nang mag-isa.
- Ang recursive CTE ay tumutukoy sa sarili nito. May dalawa itong bahaging pinagsama ng
UNION ALL: isang panimulang SELECT (ang mga unang row) at isang recursive SELECT na nagdaragdag ng mga bagong row mula sa mga row na nahanap na. Humihinto ito kapag walang bagong row na ibinalik ang recursive na bahagi. - Laging bigyan ang recursive CTE ng malinaw na kondisyon ng paghinto (isang WHERE tulad ng
x < 5). Iminumungkahi rin ng dokumentasyon ng SQLite na magdagdag ng LIMIT bilang pananggalang kapag alam mo ang pinakamataas na laki. - Nagkakaiba sa pagitan ng mga database:
| Database | Recursive CTE keyword | Note |
|---|---|---|
| SQLite | WITH RECURSIVE (hindi pinipilit ng SQLite ang keyword) | Mga MATERIALIZED / NOT MATERIALIZED hint mula sa bersyon 3.35.0 |
| PostgreSQL | WITH RECURSIVE | Ang CTE na minsan lang ginamit ay karaniwang isinasama sa pangunahing query; ang MATERIALIZED ay pumipilit na kuwentahin ito nang hiwalay |
| SQL Server | karaniwang WITH (walang RECURSIVE keyword) | Ang default na limitasyon ng recursion ay 100 antas; baguhin ito gamit ang OPTION (MAXRECURSION n) |
Mga customer na mas malaki ang ginastos kaysa sa karaniwang customer (lahat ng order, tulad sa course 7.4.2):
WITH customer_totals AS ( SELECT customer_id, customer, SUM(line_total) AS total FROM order_lines GROUP BY customer_id, customer ) SELECT customer, total FROM customer_totals WHERE total > (SELECT AVG(total) FROM customer_totals) ORDER BY total DESC;
Resulta: Ana 132.0, Dev 98.0. Isang beses isinulat ang CTE at dalawang beses ginamit.
WITH paid AS (
SELECT * FROM order_lines WHERE status = 'paid'
),
by_month AS (
SELECT strftime('%Y-%m', order_date) AS month,
COUNT(DISTINCT order_id) AS orders,
SUM(line_total) AS revenue
FROM paid
GROUP BY month
)
SELECT month, orders, revenue, ROUND(revenue / orders, 2) AS avg_order
FROM by_month
ORDER BY month;
Resulta: 2026-09: 1 order, 33.0, 33.0; 2026-10: 3, 156.5, 52.17; 2026-11: 2, 113.0, 56.5.
WITH RECURSIVE chain(id, name, level) AS ( SELECT id, name, 0 FROM customers WHERE id = 1 UNION ALL SELECT c.id, c.name, chain.level + 1 FROM customers c JOIN chain ON c.referred_by = chain.id ) SELECT name, level FROM chain ORDER BY level, name;
Resulta: Ana 0, Ben 1, Chloe 1, Dev 2. Si Dev ay inirekomenda ni Ben, na inirekomenda ni Ana.
WITH RECURSIVE months(m) AS (
SELECT '2026-08-01'
UNION ALL
SELECT date(m, '+1 month') FROM months WHERE m < '2026-12-01'
)
SELECT strftime('%Y-%m', months.m) AS month,
COALESCE(SUM(ol.line_total), 0) AS revenue
FROM months
LEFT JOIN order_lines ol
ON strftime('%Y-%m', ol.order_date) = strftime('%Y-%m', months.m)
AND ol.status = 'paid'
GROUP BY months.m
ORDER BY months.m;
Resulta: 2026-08: 0, 2026-09: 33.0, 2026-10: 156.5, 2026-11: 113.0, 2026-12: 0. Kung walang listahan ng buwan, mawawala ang Agosto at Disyembre, at itatago ng chart ang mga walang lamang buwan.
- Buksan ang
shop2.dbmo mula sa course 7.4.2 (o buuin muli ang apat na table at angorder_linesview). - Patakbuhin muna ang panloob na SELECT lang ng
customer_totals. Check: 4 na row (Ana, Ben, Chloe, Dev). - Balutin ito ng
WITH customer_totals AS (...)at idagdag ang pangunahing SELECT. Check: Ana at Dev. - Patakbuhin ang dalawang-CTE na buwanang query. Tapos palitan ang huling linya ng
SELECT * FROM paid;para tingnan ang loob ng unang hakbang. - Patakbuhin ang
WITH RECURSIVE n(x) AS (SELECT 1 UNION ALL SELECT x + 1 FROM n WHERE x < 5) SELECT x FROM n;at tiyaking 1 hanggang 5 ang makukuha mo. - Patakbuhin ang referral chain query at iguhit ang kadena sa papel: Ana, tapos Ben at Chloe, tapos Dev.
- Patakbuhin ang month-list query. Check: limang buwan, na may 0 para sa Agosto at Disyembre.
Videos by other creators on YouTube, for reference. They are not made by or affiliated with The Future Market.
Read the video script
[Host] "Mahirap basahin ang mahahabang query. Hinahayaan ka ng mga CTE na pangalanan ang bawat hakbang."
[Screen: naka-highlight ang WITH customer_totals AS ( ... )] "Isulat ang hakbang nang minsan, bigyan ng pangalan, gamitin na parang table. Dito, dalawang beses natin itong ginagamit."
[Screen: referral chain na Ana papuntang Ben papuntang Dev] "Inuulit ng recursive CTE ang isang hakbang hanggang wala nang bagong makita. Ganyan mo susundan ang kadena ng mga referral."
[Text on screen: laging magdagdag ng kondisyon ng paghinto] "Laging bigyan ito ng paraan para huminto, tulad ng x na mas mababa sa 5."
- Sumulat ng CTE na
city_revenuena may bayad na revenue kada city (mula saorder_lines), tapos ipakita lang ang mga city na mas mataas sa average na revenue ng city. Check: ang Toronto 230.0 ay mas mataas sa average; ang Hamilton 72.5 ay hindi. - Sumulat ng recursive CTE na naglilista ng bawat araw mula 2026-11-01 hanggang 2026-11-07. Check: 7 na row.
ClaudeStuck? Copy a ready-made prompt for Claude
Copy this, open Claude, paste it, and Claude will walk you through the lesson step by step.
For a grown-up: Claude is for adults (18+). Copy this, paste it into Claude, and use the answer to explain the lesson to your child.
I'm learning "Advanced SQL: window functions at performance" on The Future Market. Lesson 1: "Bago ka magsimula, at mga CTE: pagpapangalan sa mga hakbang ng query". What the lesson teaches: - Ang CTE (common table expression) ay isang SELECT na may pangalan, nakasulat sa itaas ng query gamit ang WITH name AS (...). Magagamit na ng pangunahing query ang name na parang table. - Puwede kang magsulat ng ilang CTE sa isang WITH, pinaghihiwalay ng kuwit. Magagamit ng sumunod na CTE ang nauna. - Umiiral lang ang CTE habang tumatakbo ang isang query na iyon. Ang view (course 7.4.2) ay naka-save sa database; ang CTE ay hindi. - Ginagawang nababasa ng mga CTE ang mahahabang query: may pangalan ang bawat hakbang at masusubukan mo ang bawat hakbang nang mag-isa. - Ang recursive CTE ay tumutukoy sa sarili nito. May dalawa itong bahaging pinagsama ng UNION ALL: isang panimulang SELECT (ang mga unang row) at isang recursive SELECT na nagdaragdag ng mga bagong row mula sa mga row na nahanap na. Humihinto ito kapag walang bagong row na ibinalik ang recursive na bahagi. - Laging bigyan ang recursive CTE ng malinaw na kondisyon ng paghinto (isang WHERE tulad ng x < 5). Iminumungkahi rin ng dokumentasyon ng SQLite na magdagdag ng LIMIT bilang pananggalang kapag alam mo ang pinakamataas na laki. - Nagkakaiba sa pagitan ng mga database: The exercise I'm working on: 1. Sumulat ng CTE na city_revenue na may bayad na revenue kada city (mula sa order_lines), tapos ipakita lang ang mga city na mas mataas sa average na revenue ng city. Check: ang Toronto 230.0 ay mas mataas sa average; ang Hamilton 72.5 ay hindi. 2. Sumulat ng recursive CTE na naglilista ng bawat araw mula 2026-11-01 hanggang 2026-11-07. Check: 7 na row. I'm stuck. Please: 1. Explain the main idea in plain, simple words with one everyday example. 2. Walk me through the exercise one small step at a time. Ask me what I've done so far before giving the next step. 3. Don't just give me the final answer. Help me do it myself, and check my work when I share it.
I'm a parent helping my child (about 8 years old) with a lesson called "Bago ka magsimula, at mga CTE: pagpapangalan sa mga hakbang ng query" from the course "Advanced SQL: window functions at performance". Here's what the lesson says: Kapag nagluluto ka ng malaking handaan, naghahanda ka muna ng maliliit na mangkok: tinadtad na sibuyas, hinugasang bigas, hinalong sarsa. May pangalan ang bawat mangkok. Tapos pagsasamahin mo. Ang CTE ay maliit na mangkok na may pangalan sa loob ng isang query. The activity: 1. Sumulat ng CTE na city_revenue na may bayad na revenue kada city (mula sa order_lines), tapos ipakita lang ang mga city na mas mataas sa average na revenue ng city. Check: ang Toronto 230.0 ay mas mataas sa average; ang Hamilton 72.5 ay hindi. 2. Sumulat ng recursive CTE na naglilista ng bawat araw mula 2026-11-01 hanggang 2026-11-07. Check: 7 na row. Please explain this so an 8-year-old understands: short sentences, a fun everyday example, and no hard words. Then give me 3 simple questions I can ask my child to check they understood, and a way to do the activity together, one tiny step at a time.
Sources
- SQLite, the WITH clause (CTEs, recursive CTEs, MATERIALIZED hints, LIMIT advice): www.sqlite.org/lang_with.html
- PostgreSQL documentation, WITH queries: www.postgresql.org/docs/current/queries-with.html
- Microsoft Learn, WITH common_table_expression (Transact-SQL): learn.microsoft.com/en-us/sql/t-sql/queries/with-common-table-expressi
Window functions: mag-rank ng mga row nang hindi sila nawawala
This lesson is part of full access: every course and every level for one payment.
Running total, moving average at window frame
This lesson is part of full access: every course and every level for one payment.
LAG, LEAD at paghahambing ng mga row
This lesson is part of full access: every course and every level for one payment.
Mga index: paano mabilis na nahahanap ng database ang mga row
This lesson is part of full access: every course and every level for one payment.
Pagbasa ng mga query plan at pagsulat ng mga filter na magiliw sa index
This lesson is part of full access: every course and every level for one payment.
Pagpapabilis ng mabagal na query, hakbang-hakbang (project lesson)
This lesson is part of full access: every course and every level for one payment.
Final project
This lesson is part of full access: every course and every level for one payment.
Quiz
Ano ang CTE?
Isang SELECT na may pangalan, isinulat gamit ang WITH sa itaas ng query, na magagamit ng pangunahing query na parang table.
Anong dalawang bahagi ang mayroon ang recursive CTE?
Isang panimulang SELECT at isang recursive SELECT na pinagsama ng UNION ALL, kasama ang kondisyong nagpapahinto rito.
Ano ang pangunahing pagkakaiba ng window function at GROUP BY?
Pinapanatili ng window function ang bawat row at nagdaragdag ng kinuwentang column; pinipiga ng GROUP BY ang mga row sa isa kada group.
Para sa mga value na 5, 5, 4, ano ang ibinibigay ng RANK at DENSE_RANK?
Ang RANK ay nagbibigay ng 1, 1, 3; ang DENSE_RANK ay nagbibigay ng 1, 1, 2.
Bakit hindi mo maisusulat ang
WHERE rn = 1sa parehong SELECT na kumukuwenta ngROW_NUMBER() ... AS rn?Kinukuwenta ang mga window function pagkatapos ng WHERE, kaya nagfi-filter ka sa panlabas na query (halimbawa isang CTE).
Ano ang ibig sabihin ng
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW?Gamitin ang row na ito at ang dalawang row bago nito (3-row na gumagalaw na bintana).
Bakit puwedeng magpakita ng parehong running total ang dalawang row na may parehong petsa bilang default?
Ang default na frame ay RANGE, na nagdaragdag ng mga row na may parehong value ng ORDER BY (peers) nang sabay.
Ano ang ibinabalik ng LAG para sa unang row?
NULL, maliban kung magbigay ka ng default na value.
Ano ang ibig sabihin ng SCAN sa query plan ng SQLite?
Binabasa ng database ang bawat row (full scan).
Bakit mabagal ang
WHERE strftime('%Y-%m', visit_date) = '2026-03'sa malaking table?Nakabalot sa function ang column, kaya hindi magagamit ang index para tumalon sa mga row; ang saklaw ng petsa ay magagamit.
Magbanggit ng isang kapalit ng pagdaragdag ng index.
Mas maraming trabaho ang mga insert, update at delete, at kumukuha ang index ng dagdag na espasyo.
Pagkatapos isulat muli ang query para pabilisin ito, paano mo mapapatunayang hindi nagbago ang sagot?
Ihambing ang luma at bagong resulta gamit ang EXCEPT sa dalawang direksyon; dapat 0 ang parehong bilang.
Final exam
This lesson is part of full access: every course and every level for one payment.
Certificate
This lesson is part of full access: every course and every level for one payment.