A subquery (also called an inner query or nested query) is a query inside another SQL query.
It’s used to filter, compare, or derive values dynamically.
🧠 Why Use Subqueries?
To compare data between tables
To fetch data based on other query results
To use aggregates (like
MAX,AVG) in filters
📦 Basic Structure
SELECT name, age
FROM students
WHERE age > (
SELECT AVG(age) FROM students
);🧠 The inner SELECT runs first, then its result is used by the outer query
🔁 Example 1: Subquery in WHERE (Scalar)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Subquery in WHERE — Try It Yourself</title>
<style>
.infographic-subqueryrunner {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--good: #16a34a;
--good-soft: #dcfce7;
--on-accent: #ffffff;
--display-font: Georgia, 'Iowan Old Style', serif;
--body-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
--mono-font: 'SF Mono', Consolas, monospace;
background: var(--paper);
color: var(--ink);
font-family: var(--body-font);
max-width: 760px;
margin: 0 auto;
box-sizing: border-box;
overflow-x: hidden;
}
.infographic-subqueryrunner[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
--good: #4ade80;
--good-soft: #123420;
--on-accent: #101418;
}
.infographic-subqueryrunner * { box-sizing: border-box; }
.sb-frame { background: var(--paper-alt); border: 1px solid var(--line); border-radius: 10px; padding: 1.25rem; }
.sb-kw { color: #9cc5ff; } .sb-str { color: #f8d980; } .sb-num { color: #4ade80; } .sb-cm { color: #7c8aa8; }
.sb-code-scroll { overflow-x: auto; }
.sb-code {
background: var(--ink); color: #d4e2ff; border-radius: 8px; padding: 0.9rem 1.1rem;
font-family: var(--mono-font); font-size: 0.8rem; line-height: 1.65; white-space: pre;
display: inline-block;
min-width: 100%;
}
.infographic-subqueryrunner[data-theme="dark"] .sb-code { background: #05070a; }
.sb-inner { text-decoration: underline; text-decoration-color: var(--accent); text-decoration-thickness: 2px; }
.sb-output-label { font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-soft); margin: 1.1rem 0 0.6rem; }
.sb-table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; min-width: 0; }
table.sb-table {
width: 100%; min-width: 260px; border-collapse: collapse; background: var(--paper);
border-radius: 8px; font-size: 0.88rem;
}
table.sb-table th, table.sb-table td {
border: 1px solid var(--line); padding: 0.5rem 0.7rem; text-align: left; white-space: nowrap;
transition: background 0.4s, color 0.4s;
}
table.sb-table th { background: var(--accent); color: var(--on-accent); font-weight: 700; font-size: 0.75rem; }
table.sb-table tr.is-checking td { background: var(--accent-soft); }
table.sb-table tr.is-match td { background: var(--good-soft); color: var(--good); font-weight: 700; }
table.sb-table td.is-maxcell { color: var(--accent); font-weight: 700; }
.sb-run-row { display: flex; justify-content: center; gap: 0.6rem; margin-top: 1.1rem; flex-wrap: wrap; }
.sb-run-btn {
font: inherit; font-size: 0.85rem; background: var(--accent); color: var(--on-accent);
border: none; border-radius: 7px; padding: 0.6rem 1.2rem; cursor: pointer;
}
.sb-run-btn:hover { opacity: 0.9; }
.sb-run-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.sb-run-btn.is-secondary { background: var(--paper); color: var(--ink); border: 1px solid var(--line); }
.sb-log-scroll { overflow-x: auto; margin-top: 1.1rem; }
.sb-log {
background: var(--ink); color: #d4e2ff; border-radius: 8px; padding: 0.75rem 0.9rem;
font-family: var(--mono-font); font-size: 0.78rem; line-height: 1.65; min-height: 1.5rem;
}
.infographic-subqueryrunner[data-theme="dark"] .sb-log { background: #05070a; }
.sb-log-line { opacity: 0; animation: sb-line-in 0.25s ease forwards; }
@keyframes sb-line-in { to { opacity: 1; } }
.sb-log-placeholder { color: #7c8aa8; font-style: italic; }
.sb-result-label { font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-soft); margin: 1.1rem 0 0.6rem; display: none; }
.sb-result-label.is-visible { display: block; }
.sb-result-scroll { overflow-x: auto; display: none; }
.sb-result-scroll.is-visible { display: block; }
table.sb-result-table {
width: 100%; min-width: 140px; border-collapse: collapse; background: var(--paper);
border-radius: 8px; font-size: 0.88rem;
}
table.sb-result-table th, table.sb-result-table td {
border: 1px solid var(--line); padding: 0.5rem 0.7rem; text-align: left; white-space: nowrap;
}
table.sb-result-table th { background: var(--good); color: #fff; font-weight: 700; font-size: 0.75rem; }
table.sb-result-table tr.is-new td { animation: sb-row-in 0.5s ease; }
@keyframes sb-row-in { from { background: var(--good-soft); } to { background: transparent; } }
@media (prefers-reduced-motion: reduce) {
.infographic-subqueryrunner *, .infographic-subqueryrunner *::before, .infographic-subqueryrunner *::after {
transition-duration: 0.001ms !important; animation-duration: 0.001ms !important;
}
}
</style>
</head>
<body>
<div class="infographic-subqueryrunner" id="subqueryrunner">
<div class="sb-frame">
<div class="sb-code-scroll">
<div class="sb-code"><span class="sb-kw">CREATE TABLE</span> students (
id <span class="sb-kw">INT AUTO_INCREMENT PRIMARY KEY</span>,
name <span class="sb-kw">VARCHAR</span>(50) <span class="sb-kw">NOT NULL</span>,
marks <span class="sb-kw">INT</span> <span class="sb-kw">NOT NULL</span>
);
<span class="sb-kw">INSERT INTO</span> students (name, marks) <span class="sb-kw">VALUES</span>
(<span class="sb-str">'Anya'</span>, <span class="sb-num">86</span>),
(<span class="sb-str">'Raj'</span>, <span class="sb-num">91</span>),
(<span class="sb-str">'Sara'</span>, <span class="sb-num">78</span>),
(<span class="sb-str">'Ravi'</span>, <span class="sb-num">91</span>),
(<span class="sb-str">'Tina'</span>, <span class="sb-num">88</span>);
<span class="sb-kw">SELECT</span> name
<span class="sb-kw">FROM</span> students
<span class="sb-kw">WHERE</span> marks = (<span class="sb-inner"><span class="sb-kw">SELECT</span> <span class="sb-kw">MAX</span>(marks) <span class="sb-kw">FROM</span> students</span>);</div>
</div>
<p class="sb-output-label">Table: students</p>
<div class="sb-table-scroll">
<table class="sb-table" id="sbTable">
<thead><tr><th>id</th><th>name</th><th>marks</th></tr></thead>
<tbody></tbody>
</table>
</div>
<div class="sb-run-row">
<button class="sb-run-btn" id="sbSetupBtn" type="button">▶ Run Setup</button>
<button class="sb-run-btn" id="sbRunBtn" type="button" disabled>▶ Run the query</button>
<button class="sb-run-btn is-secondary" id="sbReset" type="button">↺ Reset</button>
</div>
<div class="sb-log-scroll">
<div class="sb-log" id="sbLog"><span class="sb-log-placeholder">Run Setup, then run the query to see it evaluate step by step...</span></div>
</div>
<p class="sb-result-label" id="sbResultLabel">Query Result</p>
<div class="sb-result-scroll" id="sbResultScroll">
<table class="sb-result-table" id="sbResultTable"><thead><tr><th>name</th></tr></thead><tbody id="sbResultBody"></tbody></table>
</div>
</div>
</div>
<script>
(function () {
const wrapper = document.getElementById('subqueryrunner');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') {
dark = true;
} else if (bodyAttr === 'false') {
dark = false;
} else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
})();
(function () {
const students = [
{ id: 1, name: 'Anya', marks: 86 },
{ id: 2, name: 'Raj', marks: 91 },
{ id: 3, name: 'Sara', marks: 78 },
{ id: 4, name: 'Ravi', marks: 91 },
{ id: 5, name: 'Tina', marks: 88 }
];
const table = document.getElementById('sbTable');
const tbody = table.querySelector('tbody');
const setupBtn = document.getElementById('sbSetupBtn');
const runBtn = document.getElementById('sbRunBtn');
const log = document.getElementById('sbLog');
const resultLabel = document.getElementById('sbResultLabel');
const resultScroll = document.getElementById('sbResultScroll');
const resultBody = document.getElementById('sbResultBody');
function clearLog() { log.innerHTML = ''; }
function appendLog(text) {
if (log.querySelector('.sb-log-placeholder')) log.innerHTML = '';
const line = document.createElement('div');
line.className = 'sb-log-line';
line.textContent = text;
log.appendChild(line);
}
function delay(ms) { return new Promise(res => setTimeout(res, ms)); }
function renderStudents() {
tbody.innerHTML = students.map(s =>
'<tr data-id="' + s.id + '"><td>' + s.id + '</td><td>' + s.name + '</td><td>' + s.marks + '</td></tr>'
).join('');
}
setupBtn.addEventListener('click', () => {
setupBtn.disabled = true;
renderStudents();
runBtn.disabled = false;
appendLog('Table created, 5 rows inserted.');
});
runBtn.addEventListener('click', async () => {
runBtn.disabled = true;
clearLog();
resultLabel.classList.remove('is-visible');
resultScroll.classList.remove('is-visible');
resultBody.innerHTML = '';
tbody.querySelectorAll('tr').forEach(tr => tr.classList.remove('is-checking', 'is-match'));
tbody.querySelectorAll('td').forEach(td => td.classList.remove('is-maxcell'));
appendLog('Step 1 — run the inner subquery first: SELECT MAX(marks) FROM students');
await delay(400);
let maxSoFar = -Infinity;
for (const s of students) {
const tr = tbody.querySelector('tr[data-id="' + s.id + '"]');
tbody.querySelectorAll('tr').forEach(t => t.classList.remove('is-checking'));
tr.classList.add('is-checking');
appendLog('Checking marks = ' + s.marks + (s.marks > maxSoFar ? ' → new highest so far' : ''));
if (s.marks > maxSoFar) maxSoFar = s.marks;
await delay(280);
}
tbody.querySelectorAll('tr').forEach(t => t.classList.remove('is-checking'));
appendLog('Inner subquery result: MAX(marks) = ' + maxSoFar);
await delay(300);
appendLog('Step 2 — run the outer query: WHERE marks = ' + maxSoFar);
await delay(300);
const matches = students.filter(s => s.marks === maxSoFar);
matches.forEach(s => {
const tr = tbody.querySelector('tr[data-id="' + s.id + '"]');
tr.classList.add('is-match');
tr.children[2].classList.add('is-maxcell');
});
appendLog(matches.length + ' row(s) matched: ' + matches.map(s => s.name).join(', '));
resultBody.innerHTML = matches.map(s => '<tr class="is-new"><td>' + s.name + '</td></tr>').join('');
resultLabel.classList.add('is-visible');
resultScroll.classList.add('is-visible');
resultScroll.scrollIntoView({ behavior: 'smooth', block: 'center' });
runBtn.disabled = false;
});
document.getElementById('sbReset').addEventListener('click', () => {
tbody.innerHTML = '';
clearLog();
log.innerHTML = '<span class="sb-log-placeholder">Run Setup, then run the query to see it evaluate step by step...</span>';
resultLabel.classList.remove('is-visible');
resultScroll.classList.remove('is-visible');
resultBody.innerHTML = '';
setupBtn.disabled = false;
runBtn.disabled = true;
});
})();
</script>
</body>
</html>.demo {
font-family: system-ui, sans-serif;
padding: 16px;
}
.demo h1 {
color: #2563eb;
margin: 0 0 8px;
}
.demo p {
color: #4b5563;
margin: 0;
}document.querySelector('.demo h1')?.addEventListener('click', () => {
alert('Hello from live preview!');
});✔️ Returns student(s) with highest marks
🧾 Example 2: Subquery with IN (Multiple Values)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Subquery with IN — Try It Yourself</title>
<style>
.infographic-subqueryinrunner {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--good: #16a34a;
--good-soft: #dcfce7;
--on-accent: #ffffff;
--display-font: Georgia, 'Iowan Old Style', serif;
--body-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
--mono-font: 'SF Mono', Consolas, monospace;
background: var(--paper);
color: var(--ink);
font-family: var(--body-font);
max-width: 800px;
margin: 0 auto;
box-sizing: border-box;
overflow-x: hidden;
}
.infographic-subqueryinrunner[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
--good: #4ade80;
--good-soft: #123420;
--on-accent: #101418;
}
.infographic-subqueryinrunner * { box-sizing: border-box; }
.si-frame { background: var(--paper-alt); border: 1px solid var(--line); border-radius: 10px; padding: 1.25rem; }
.si-kw { color: #9cc5ff; } .si-str { color: #f8d980; } .si-num { color: #4ade80; } .si-cm { color: #7c8aa8; }
.si-code-scroll { overflow-x: auto; }
.si-code {
background: var(--ink); color: #d4e2ff; border-radius: 8px; padding: 0.9rem 1.1rem;
font-family: var(--mono-font); font-size: 0.78rem; line-height: 1.6; white-space: pre;
display: inline-block;
min-width: 100%;
}
.infographic-subqueryinrunner[data-theme="dark"] .si-code { background: #05070a; }
.si-inner { text-decoration: underline; text-decoration-color: var(--accent); text-decoration-thickness: 2px; }
.si-src-row { display: flex; gap: 1rem; flex-wrap: wrap; margin-top: 1.1rem; }
.si-src-col { flex: 1 1 220px; min-width: 0; }
.si-table-name { font-size: 0.72rem; color: var(--ink-soft); text-transform: uppercase; letter-spacing: 0.04em; margin: 0 0 0.4rem; }
.si-table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; min-width: 0; }
table.si-table {
width: 100%; min-width: 180px; border-collapse: collapse; background: var(--paper);
border-radius: 8px; font-size: 0.85rem;
}
table.si-table th, table.si-table td {
border: 1px solid var(--line); padding: 0.45rem 0.6rem; text-align: left; white-space: nowrap;
transition: background 0.4s, color 0.4s;
}
table.si-table th { background: var(--accent); color: var(--on-accent); font-weight: 700; font-size: 0.7rem; }
table.si-table tr.is-checking td { background: var(--accent-soft); }
table.si-table tr.is-match td { background: var(--good-soft); color: var(--good); font-weight: 700; }
.si-run-row { display: flex; justify-content: center; gap: 0.6rem; margin-top: 1.1rem; flex-wrap: wrap; }
.si-run-btn {
font: inherit; font-size: 0.85rem; background: var(--accent); color: var(--on-accent);
border: none; border-radius: 7px; padding: 0.6rem 1.2rem; cursor: pointer;
}
.si-run-btn:hover { opacity: 0.9; }
.si-run-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.si-run-btn.is-secondary { background: var(--paper); color: var(--ink); border: 1px solid var(--line); }
.si-log-scroll { overflow-x: auto; margin-top: 1.1rem; }
.si-log {
background: var(--ink); color: #d4e2ff; border-radius: 8px; padding: 0.75rem 0.9rem;
font-family: var(--mono-font); font-size: 0.78rem; line-height: 1.65; min-height: 1.5rem;
}
.infographic-subqueryinrunner[data-theme="dark"] .si-log { background: #05070a; }
.si-log-line { opacity: 0; animation: si-line-in 0.25s ease forwards; }
@keyframes si-line-in { to { opacity: 1; } }
.si-log-placeholder { color: #7c8aa8; font-style: italic; }
.si-log-set { color: #f472b6; }
.si-result-label { font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-soft); margin: 1.1rem 0 0.6rem; display: none; }
.si-result-label.is-visible { display: block; }
.si-result-scroll { overflow-x: auto; display: none; }
.si-result-scroll.is-visible { display: block; }
table.si-result-table {
width: 100%; min-width: 140px; border-collapse: collapse; background: var(--paper);
border-radius: 8px; font-size: 0.88rem;
}
table.si-result-table th, table.si-result-table td {
border: 1px solid var(--line); padding: 0.5rem 0.7rem; text-align: left; white-space: nowrap;
}
table.si-result-table th { background: var(--good); color: #fff; font-weight: 700; font-size: 0.75rem; }
table.si-result-table tr.is-new td { animation: si-row-in 0.5s ease; }
@keyframes si-row-in { from { background: var(--good-soft); } to { background: transparent; } }
@media (prefers-reduced-motion: reduce) {
.infographic-subqueryinrunner *, .infographic-subqueryinrunner *::before, .infographic-subqueryinrunner *::after {
transition-duration: 0.001ms !important; animation-duration: 0.001ms !important;
}
}
</style>
</head>
<body>
<div class="infographic-subqueryinrunner" id="subqueryinrunner">
<div class="si-frame">
<div class="si-code-scroll">
<div class="si-code"><span class="si-kw">CREATE TABLE</span> students (
id <span class="si-kw">INT AUTO_INCREMENT PRIMARY KEY</span>,
name <span class="si-kw">VARCHAR</span>(50) <span class="si-kw">NOT NULL</span>
);
<span class="si-kw">CREATE TABLE</span> enrollments (
student_id <span class="si-kw">INT</span>,
course <span class="si-kw">VARCHAR</span>(50),
<span class="si-kw">FOREIGN KEY</span> (student_id) <span class="si-kw">REFERENCES</span> students(id)
);
<span class="si-kw">INSERT INTO</span> students (name) <span class="si-kw">VALUES</span>
(<span class="si-str">'Anya'</span>), (<span class="si-str">'Raj'</span>), (<span class="si-str">'Sara'</span>), (<span class="si-str">'Ravi'</span>);
<span class="si-kw">INSERT INTO</span> enrollments (student_id, course) <span class="si-kw">VALUES</span>
(<span class="si-num">1</span>, <span class="si-str">'Math'</span>), (<span class="si-num">2</span>, <span class="si-str">'Science'</span>), (<span class="si-num">3</span>, <span class="si-str">'Math'</span>), (<span class="si-num">4</span>, <span class="si-str">'History'</span>);
<span class="si-kw">SELECT</span> name
<span class="si-kw">FROM</span> students
<span class="si-kw">WHERE</span> id <span class="si-kw">IN</span> (
<span class="si-inner"><span class="si-kw">SELECT</span> student_id
<span class="si-kw">FROM</span> enrollments
<span class="si-kw">WHERE</span> course = <span class="si-str">'Math'</span></span>
);</div>
</div>
<div class="si-src-row">
<div class="si-src-col">
<p class="si-table-name">students</p>
<div class="si-table-scroll"><table class="si-table" id="siStudentsTable"><thead><tr><th>id</th><th>name</th></tr></thead><tbody></tbody></table></div>
</div>
<div class="si-src-col">
<p class="si-table-name">enrollments</p>
<div class="si-table-scroll"><table class="si-table" id="siEnrollTable"><thead><tr><th>student_id</th><th>course</th></tr></thead><tbody></tbody></table></div>
</div>
</div>
<div class="si-run-row">
<button class="si-run-btn" id="siSetupBtn" type="button">▶ Run Setup</button>
<button class="si-run-btn" id="siRunBtn" type="button" disabled>▶ Run the query</button>
<button class="si-run-btn is-secondary" id="siReset" type="button">↺ Reset</button>
</div>
<div class="si-log-scroll">
<div class="si-log" id="siLog"><span class="si-log-placeholder">Run Setup, then run the query to see it evaluate step by step...</span></div>
</div>
<p class="si-result-label" id="siResultLabel">Query Result</p>
<div class="si-result-scroll" id="siResultScroll">
<table class="si-result-table" id="siResultTable"><thead><tr><th>name</th></tr></thead><tbody id="siResultBody"></tbody></table>
</div>
</div>
</div>
<script>
(function () {
const wrapper = document.getElementById('subqueryinrunner');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') {
dark = true;
} else if (bodyAttr === 'false') {
dark = false;
} else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
})();
(function () {
const students = [{ id: 1, name: 'Anya' }, { id: 2, name: 'Raj' }, { id: 3, name: 'Sara' }, { id: 4, name: 'Ravi' }];
const enrollments = [{ student_id: 1, course: 'Math' }, { student_id: 2, course: 'Science' }, { student_id: 3, course: 'Math' }, { student_id: 4, course: 'History' }];
const studentsTbody = document.querySelector('#siStudentsTable tbody');
const enrollTbody = document.querySelector('#siEnrollTable tbody');
const setupBtn = document.getElementById('siSetupBtn');
const runBtn = document.getElementById('siRunBtn');
const log = document.getElementById('siLog');
const resultLabel = document.getElementById('siResultLabel');
const resultScroll = document.getElementById('siResultScroll');
const resultBody = document.getElementById('siResultBody');
function clearLog() { log.innerHTML = ''; }
function appendLog(html) {
if (log.querySelector('.si-log-placeholder')) log.innerHTML = '';
const line = document.createElement('div');
line.className = 'si-log-line';
line.innerHTML = html;
log.appendChild(line);
}
function delay(ms) { return new Promise(res => setTimeout(res, ms)); }
function renderSource() {
studentsTbody.innerHTML = students.map(s => '<tr data-id="' + s.id + '"><td>' + s.id + '</td><td>' + s.name + '</td></tr>').join('');
enrollTbody.innerHTML = enrollments.map((e, i) => '<tr data-idx="' + i + '"><td>' + e.student_id + '</td><td>' + e.course + '</td></tr>').join('');
}
setupBtn.addEventListener('click', () => {
setupBtn.disabled = true;
renderSource();
runBtn.disabled = false;
appendLog('Both tables created, all sample data inserted.');
});
runBtn.addEventListener('click', async () => {
runBtn.disabled = true;
clearLog();
resultLabel.classList.remove('is-visible');
resultScroll.classList.remove('is-visible');
resultBody.innerHTML = '';
studentsTbody.querySelectorAll('tr').forEach(tr => tr.classList.remove('is-checking', 'is-match'));
enrollTbody.querySelectorAll('tr').forEach(tr => tr.classList.remove('is-checking', 'is-match'));
appendLog("Step 1 — run the inner subquery: find every student_id where course = 'Math'");
await delay(400);
const matchedIds = [];
for (let i = 0; i < enrollments.length; i++) {
const e = enrollments[i];
const tr = enrollTbody.querySelector('tr[data-idx="' + i + '"]');
enrollTbody.querySelectorAll('tr').forEach(t => t.classList.remove('is-checking'));
tr.classList.add('is-checking');
const isMath = e.course === 'Math';
appendLog('Row: student_id=' + e.student_id + ', course=' + e.course + (isMath ? ' ✓ matches' : ' ✕ skip'));
await delay(280);
tr.classList.remove('is-checking');
if (isMath) { tr.classList.add('is-match'); matchedIds.push(e.student_id); }
}
appendLog('Inner subquery result: IN (<span class="si-log-set">' + matchedIds.join(', ') + '</span>)');
await delay(350);
appendLog('Step 2 — run the outer query: WHERE id IN (' + matchedIds.join(', ') + ')');
await delay(300);
const matchedStudents = [];
for (const s of students) {
const tr = studentsTbody.querySelector('tr[data-id="' + s.id + '"]');
studentsTbody.querySelectorAll('tr').forEach(t => t.classList.remove('is-checking'));
tr.classList.add('is-checking');
const inSet = matchedIds.includes(s.id);
appendLog('Checking students.id=' + s.id + ' (' + s.name + ')' + (inSet ? ' ✓ in set' : ' ✕ not in set'));
await delay(260);
tr.classList.remove('is-checking');
if (inSet) { tr.classList.add('is-match'); matchedStudents.push(s); }
}
appendLog(matchedStudents.length + ' row(s) matched: ' + matchedStudents.map(s => s.name).join(', '));
resultBody.innerHTML = matchedStudents.map(s => '<tr class="is-new"><td>' + s.name + '</td></tr>').join('');
resultLabel.classList.add('is-visible');
resultScroll.classList.add('is-visible');
resultScroll.scrollIntoView({ behavior: 'smooth', block: 'center' });
runBtn.disabled = false;
});
document.getElementById('siReset').addEventListener('click', () => {
studentsTbody.innerHTML = '';
enrollTbody.innerHTML = '';
clearLog();
log.innerHTML = '<span class="si-log-placeholder">Run Setup, then run the query to see it evaluate step by step...</span>';
resultLabel.classList.remove('is-visible');
resultScroll.classList.remove('is-visible');
resultBody.innerHTML = '';
setupBtn.disabled = false;
runBtn.disabled = true;
});
})();
</script>
</body>
</html>.demo {
font-family: system-ui, sans-serif;
padding: 16px;
}
.demo h1 {
color: #2563eb;
margin: 0 0 8px;
}
.demo p {
color: #4b5563;
margin: 0;
}document.querySelector('.demo h1')?.addEventListener('click', () => {
alert('Hello from live preview!');
});✔️ Returns students enrolled in Math
💬 Example 3: Subquery in FROM (Inline View)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Subquery in FROM (Derived Table) — Try It Yourself</title>
<style>
.infographic-derivedrunner {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--good: #16a34a;
--good-soft: #dcfce7;
--on-accent: #ffffff;
--display-font: Georgia, 'Iowan Old Style', serif;
--body-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
--mono-font: 'SF Mono', Consolas, monospace;
background: var(--paper);
color: var(--ink);
font-family: var(--body-font);
max-width: 760px;
margin: 0 auto;
box-sizing: border-box;
overflow-x: hidden;
}
.infographic-derivedrunner[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
--good: #4ade80;
--good-soft: #123420;
--on-accent: #101418;
}
.infographic-derivedrunner * { box-sizing: border-box; }
.dv-frame { background: var(--paper-alt); border: 1px solid var(--line); border-radius: 10px; padding: 1.25rem; }
.dv-kw { color: #9cc5ff; } .dv-str { color: #f8d980; } .dv-num { color: #4ade80; }
.dv-inner { text-decoration: underline; text-decoration-color: var(--accent); text-decoration-thickness: 2px; }
.dv-code-scroll { overflow-x: auto; }
.dv-code {
background: var(--ink); color: #d4e2ff; border-radius: 8px; padding: 0.9rem 1.1rem;
font-family: var(--mono-font); font-size: 0.8rem; line-height: 1.65; white-space: pre;
display: inline-block;
min-width: 100%;
}
.infographic-derivedrunner[data-theme="dark"] .dv-code { background: #05070a; }
.dv-table-name { font-size: 0.72rem; color: var(--ink-soft); text-transform: uppercase; letter-spacing: 0.04em; margin: 1.1rem 0 0.4rem; }
.dv-table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; min-width: 0; }
table.dv-table {
width: 100%; min-width: 240px; border-collapse: collapse; background: var(--paper);
border-radius: 8px; font-size: 0.88rem;
}
table.dv-table th, table.dv-table td {
border: 1px solid var(--line); padding: 0.5rem 0.7rem; text-align: left; white-space: nowrap;
transition: background 0.4s, color 0.4s;
}
table.dv-table th { background: var(--accent); color: var(--on-accent); font-weight: 700; font-size: 0.75rem; }
table.dv-table tr.is-checking td { background: var(--accent-soft); }
table.dv-table td.is-sumcell { color: var(--accent); font-weight: 700; }
.dv-run-row { display: flex; justify-content: center; gap: 0.6rem; margin-top: 1.1rem; flex-wrap: wrap; }
.dv-run-btn {
font: inherit; font-size: 0.85rem; background: var(--accent); color: var(--on-accent);
border: none; border-radius: 7px; padding: 0.6rem 1.2rem; cursor: pointer;
}
.dv-run-btn:hover { opacity: 0.9; }
.dv-run-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.dv-run-btn.is-secondary { background: var(--paper); color: var(--ink); border: 1px solid var(--line); }
.dv-log-scroll { overflow-x: auto; margin-top: 1.1rem; }
.dv-log {
background: var(--ink); color: #d4e2ff; border-radius: 8px; padding: 0.75rem 0.9rem;
font-family: var(--mono-font); font-size: 0.78rem; line-height: 1.65; min-height: 1.5rem;
}
.infographic-derivedrunner[data-theme="dark"] .dv-log { background: #05070a; }
.dv-log-line { opacity: 0; animation: dv-line-in 0.25s ease forwards; }
@keyframes dv-line-in { to { opacity: 1; } }
.dv-log-placeholder { color: #7c8aa8; font-style: italic; }
.dv-derived-wrap { display: none; margin-top: 1.1rem; }
.dv-derived-wrap.is-visible { display: block; animation: dv-line-in 0.4s ease; }
table.dv-derived-table {
border-collapse: collapse; background: var(--paper); border: 2px dashed var(--accent);
border-radius: 8px; font-size: 0.88rem;
}
table.dv-derived-table th, table.dv-derived-table td {
border: 1px solid var(--line); padding: 0.55rem 0.9rem; text-align: left;
}
table.dv-derived-table th { background: var(--accent-soft); color: var(--accent); font-weight: 700; font-size: 0.75rem; }
table.dv-derived-table td { color: var(--good); font-weight: 700; }
.dv-result-label { font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-soft); margin: 1.1rem 0 0.6rem; display: none; }
.dv-result-label.is-visible { display: block; }
.dv-result-scroll { overflow-x: auto; display: none; }
.dv-result-scroll.is-visible { display: block; }
table.dv-result-table {
width: 100%; min-width: 140px; border-collapse: collapse; background: var(--paper);
border-radius: 8px; font-size: 0.88rem;
}
table.dv-result-table th, table.dv-result-table td {
border: 1px solid var(--line); padding: 0.5rem 0.7rem; text-align: left; white-space: nowrap;
}
table.dv-result-table th { background: var(--good); color: #fff; font-weight: 700; font-size: 0.75rem; }
table.dv-result-table tr.is-new td { animation: dv-row-in 0.5s ease; }
@keyframes dv-row-in { from { background: var(--good-soft); } to { background: transparent; } }
@media (prefers-reduced-motion: reduce) {
.infographic-derivedrunner *, .infographic-derivedrunner *::before, .infographic-derivedrunner *::after {
transition-duration: 0.001ms !important; animation-duration: 0.001ms !important;
}
}
</style>
</head>
<body>
<div class="infographic-derivedrunner" id="derivedrunner">
<div class="dv-frame">
<div class="dv-code-scroll">
<div class="dv-code"><span class="dv-kw">CREATE TABLE</span> students (
id <span class="dv-kw">INT AUTO_INCREMENT PRIMARY KEY</span>,
name <span class="dv-kw">VARCHAR</span>(50),
marks <span class="dv-kw">INT</span>
);
<span class="dv-kw">INSERT INTO</span> students (name, marks) <span class="dv-kw">VALUES</span>
(<span class="dv-str">'Anya'</span>, <span class="dv-num">85</span>),
(<span class="dv-str">'Raj'</span>, <span class="dv-num">90</span>),
(<span class="dv-str">'Sara'</span>, <span class="dv-num">78</span>),
(<span class="dv-str">'Ravi'</span>, <span class="dv-num">92</span>),
(<span class="dv-str">'Tina'</span>, <span class="dv-num">88</span>);
<span class="dv-kw">SELECT</span> avg_marks
<span class="dv-kw">FROM</span> (
<span class="dv-inner"><span class="dv-kw">SELECT</span> <span class="dv-kw">AVG</span>(marks) <span class="dv-kw">AS</span> avg_marks <span class="dv-kw">FROM</span> students</span>
) <span class="dv-kw">AS</span> stats;</div>
</div>
<p class="dv-table-name">students</p>
<div class="dv-table-scroll">
<table class="dv-table" id="dvTable">
<thead><tr><th>id</th><th>name</th><th>marks</th></tr></thead>
<tbody></tbody>
</table>
</div>
<div class="dv-run-row">
<button class="dv-run-btn" id="dvSetupBtn" type="button">▶ Run Setup</button>
<button class="dv-run-btn" id="dvRunBtn" type="button" disabled>▶ Run the query</button>
<button class="dv-run-btn is-secondary" id="dvReset" type="button">↺ Reset</button>
</div>
<div class="dv-log-scroll">
<div class="dv-log" id="dvLog"><span class="dv-log-placeholder">Run Setup, then run the query to see it evaluate step by step...</span></div>
</div>
<div class="dv-derived-wrap" id="dvDerivedWrap">
<p class="dv-table-name">derived table: stats</p>
<table class="dv-derived-table"><thead><tr><th>avg_marks</th></tr></thead><tbody><tr><td id="dvDerivedValue"></td></tr></tbody></table>
</div>
<p class="dv-result-label" id="dvResultLabel">Query Result</p>
<div class="dv-result-scroll" id="dvResultScroll">
<table class="dv-result-table" id="dvResultTable"><thead><tr><th>avg_marks</th></tr></thead><tbody id="dvResultBody"></tbody></table>
</div>
</div>
</div>
<script>
(function () {
const wrapper = document.getElementById('derivedrunner');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') {
dark = true;
} else if (bodyAttr === 'false') {
dark = false;
} else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
})();
(function () {
const students = [
{ id: 1, name: 'Anya', marks: 85 },
{ id: 2, name: 'Raj', marks: 90 },
{ id: 3, name: 'Sara', marks: 78 },
{ id: 4, name: 'Ravi', marks: 92 },
{ id: 5, name: 'Tina', marks: 88 }
];
const table = document.getElementById('dvTable');
const tbody = table.querySelector('tbody');
const setupBtn = document.getElementById('dvSetupBtn');
const runBtn = document.getElementById('dvRunBtn');
const log = document.getElementById('dvLog');
const derivedWrap = document.getElementById('dvDerivedWrap');
const derivedValue = document.getElementById('dvDerivedValue');
const resultLabel = document.getElementById('dvResultLabel');
const resultScroll = document.getElementById('dvResultScroll');
const resultBody = document.getElementById('dvResultBody');
function clearLog() { log.innerHTML = ''; }
function appendLog(text) {
if (log.querySelector('.dv-log-placeholder')) log.innerHTML = '';
const line = document.createElement('div');
line.className = 'dv-log-line';
line.textContent = text;
log.appendChild(line);
}
function delay(ms) { return new Promise(res => setTimeout(res, ms)); }
function renderStudents() {
tbody.innerHTML = students.map(s =>
'<tr data-id="' + s.id + '"><td>' + s.id + '</td><td>' + s.name + '</td><td>' + s.marks + '</td></tr>'
).join('');
}
setupBtn.addEventListener('click', () => {
setupBtn.disabled = true;
renderStudents();
runBtn.disabled = false;
appendLog('Table created, 5 rows inserted.');
});
runBtn.addEventListener('click', async () => {
runBtn.disabled = true;
clearLog();
derivedWrap.classList.remove('is-visible');
resultLabel.classList.remove('is-visible');
resultScroll.classList.remove('is-visible');
resultBody.innerHTML = '';
tbody.querySelectorAll('tr').forEach(tr => tr.classList.remove('is-checking'));
tbody.querySelectorAll('td').forEach(td => td.classList.remove('is-sumcell'));
appendLog('Step 1 — run the inner subquery first: SELECT AVG(marks) FROM students');
await delay(400);
let sum = 0;
for (const s of students) {
const tr = tbody.querySelector('tr[data-id="' + s.id + '"]');
tbody.querySelectorAll('tr').forEach(t => t.classList.remove('is-checking'));
tr.classList.add('is-checking');
sum += s.marks;
appendLog('Adding marks = ' + s.marks + ' → running total = ' + sum);
await delay(280);
}
tbody.querySelectorAll('tr').forEach(t => t.classList.remove('is-checking'));
const avg = Math.round((sum / students.length) * 100) / 100;
appendLog('Sum = ' + sum + ', count = ' + students.length + ' → AVG(marks) = ' + avg);
await delay(350);
appendLog('The inner query result becomes a temporary derived table called "stats" — a table that only exists for this query.');
derivedValue.textContent = avg;
derivedWrap.classList.add('is-visible');
await delay(500);
appendLog('Step 2 — run the outer query: SELECT avg_marks FROM stats');
await delay(350);
resultBody.innerHTML = '<tr class="is-new"><td>' + avg + '</td></tr>';
resultLabel.classList.add('is-visible');
resultScroll.classList.add('is-visible');
appendLog('1 row returned: avg_marks = ' + avg);
resultScroll.scrollIntoView({ behavior: 'smooth', block: 'center' });
runBtn.disabled = false;
});
document.getElementById('dvReset').addEventListener('click', () => {
tbody.innerHTML = '';
clearLog();
log.innerHTML = '<span class="dv-log-placeholder">Run Setup, then run the query to see it evaluate step by step...</span>';
derivedWrap.classList.remove('is-visible');
resultLabel.classList.remove('is-visible');
resultScroll.classList.remove('is-visible');
resultBody.innerHTML = '';
setupBtn.disabled = false;
runBtn.disabled = true;
});
})();
</script>
</body>
</html>.demo {
font-family: system-ui, sans-serif;
padding: 16px;
}
.demo h1 {
color: #2563eb;
margin: 0 0 8px;
}
.demo p {
color: #4b5563;
margin: 0;
}document.querySelector('.demo h1')?.addEventListener('click', () => {
alert('Hello from live preview!');
});✔️ Subquery acts like a temporary table
📊 Example 4: Subquery in SELECT (Scalar Value)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Correlated Subquery — Try It Yourself</title>
<style>
.infographic-correlatedrunner {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--good: #16a34a;
--good-soft: #dcfce7;
--on-accent: #ffffff;
--display-font: Georgia, 'Iowan Old Style', serif;
--body-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
--mono-font: 'SF Mono', Consolas, monospace;
background: var(--paper);
color: var(--ink);
font-family: var(--body-font);
max-width: 800px;
margin: 0 auto;
box-sizing: border-box;
overflow-x: hidden;
}
.infographic-correlatedrunner[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
--good: #4ade80;
--good-soft: #123420;
--on-accent: #101418;
}
.infographic-correlatedrunner * { box-sizing: border-box; }
.cq-frame { background: var(--paper-alt); border: 1px solid var(--line); border-radius: 10px; padding: 1.25rem; }
.cq-kw { color: #9cc5ff; } .cq-str { color: #f8d980; } .cq-num { color: #4ade80; } .cq-cm { color: #7c8aa8; }
.cq-inner { text-decoration: underline; text-decoration-color: var(--accent); text-decoration-thickness: 2px; }
.cq-code-scroll { overflow-x: auto; }
.cq-code {
background: var(--ink); color: #d4e2ff; border-radius: 8px; padding: 0.9rem 1.1rem;
font-family: var(--mono-font); font-size: 0.76rem; line-height: 1.6; white-space: pre;
display: inline-block;
min-width: 100%;
}
.infographic-correlatedrunner[data-theme="dark"] .cq-code { background: #05070a; }
.cq-src-row { display: flex; gap: 1rem; flex-wrap: wrap; margin-top: 1.1rem; }
.cq-src-col { flex: 1 1 220px; min-width: 0; }
.cq-table-name { font-size: 0.72rem; color: var(--ink-soft); text-transform: uppercase; letter-spacing: 0.04em; margin: 0 0 0.4rem; }
.cq-table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; min-width: 0; }
table.cq-table {
width: 100%; min-width: 170px; border-collapse: collapse; background: var(--paper);
border-radius: 8px; font-size: 0.85rem;
}
table.cq-table th, table.cq-table td {
border: 1px solid var(--line); padding: 0.45rem 0.6rem; text-align: left; white-space: nowrap;
transition: background 0.4s, color 0.4s;
}
table.cq-table th { background: var(--accent); color: var(--on-accent); font-weight: 700; font-size: 0.7rem; }
table.cq-table tr.is-outer-current td { background: var(--accent-soft); }
table.cq-table tr.is-inner-checking td { background: var(--good-soft); }
table.cq-table tr.is-inner-match td { color: var(--good); font-weight: 700; }
table.cq-table td.is-count { color: var(--accent); font-weight: 700; }
.cq-run-row { display: flex; justify-content: center; gap: 0.6rem; margin-top: 1.1rem; flex-wrap: wrap; }
.cq-run-btn {
font: inherit; font-size: 0.85rem; background: var(--accent); color: var(--on-accent);
border: none; border-radius: 7px; padding: 0.6rem 1.2rem; cursor: pointer;
}
.cq-run-btn:hover { opacity: 0.9; }
.cq-run-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.cq-run-btn.is-secondary { background: var(--paper); color: var(--ink); border: 1px solid var(--line); }
.cq-log-scroll { overflow-x: auto; margin-top: 1.1rem; }
.cq-log {
background: var(--ink); color: #d4e2ff; border-radius: 8px; padding: 0.75rem 0.9rem;
font-family: var(--mono-font); font-size: 0.76rem; line-height: 1.6; min-height: 1.5rem;
}
.infographic-correlatedrunner[data-theme="dark"] .cq-log { background: #05070a; }
.cq-log-line { opacity: 0; animation: cq-line-in 0.25s ease forwards; }
.cq-log-line.is-heading { color: #93c5fd; font-weight: 700; margin-top: 0.4rem; }
@keyframes cq-line-in { to { opacity: 1; } }
.cq-log-placeholder { color: #7c8aa8; font-style: italic; }
.cq-result-label { font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-soft); margin: 1.1rem 0 0.6rem; display: none; }
.cq-result-label.is-visible { display: block; }
.cq-result-scroll { overflow-x: auto; display: none; }
.cq-result-scroll.is-visible { display: block; }
table.cq-result-table {
width: 100%; min-width: 200px; border-collapse: collapse; background: var(--paper);
border-radius: 8px; font-size: 0.88rem;
}
table.cq-result-table th, table.cq-result-table td {
border: 1px solid var(--line); padding: 0.5rem 0.7rem; text-align: left; white-space: nowrap;
}
table.cq-result-table th { background: var(--good); color: #fff; font-weight: 700; font-size: 0.75rem; }
table.cq-result-table tr.is-new td { animation: cq-row-in 0.5s ease; }
@keyframes cq-row-in { from { background: var(--good-soft); } to { background: transparent; } }
@media (prefers-reduced-motion: reduce) {
.infographic-correlatedrunner *, .infographic-correlatedrunner *::before, .infographic-correlatedrunner *::after {
transition-duration: 0.001ms !important; animation-duration: 0.001ms !important;
}
}
</style>
</head>
<body>
<div class="infographic-correlatedrunner" id="correlatedrunner">
<div class="cq-frame">
<div class="cq-code-scroll">
<div class="cq-code"><span class="cq-kw">CREATE TABLE</span> students (
id <span class="cq-kw">INT AUTO_INCREMENT PRIMARY KEY</span>,
name <span class="cq-kw">VARCHAR</span>(50)
);
<span class="cq-kw">CREATE TABLE</span> enrollments (
id <span class="cq-kw">INT AUTO_INCREMENT PRIMARY KEY</span>,
student_id <span class="cq-kw">INT</span>,
course <span class="cq-kw">VARCHAR</span>(50),
<span class="cq-kw">FOREIGN KEY</span> (student_id) <span class="cq-kw">REFERENCES</span> students(id)
);
<span class="cq-kw">INSERT INTO</span> students (name) <span class="cq-kw">VALUES</span>
(<span class="cq-str">'Anya'</span>), (<span class="cq-str">'Raj'</span>), (<span class="cq-str">'Sara'</span>);
<span class="cq-kw">INSERT INTO</span> enrollments (student_id, course) <span class="cq-kw">VALUES</span>
(<span class="cq-num">1</span>, <span class="cq-str">'Math'</span>), (<span class="cq-num">1</span>, <span class="cq-str">'Science'</span>), (<span class="cq-num">2</span>, <span class="cq-str">'Math'</span>);
<span class="cq-kw">SELECT</span> name,
(<span class="cq-inner"><span class="cq-kw">SELECT</span> <span class="cq-kw">COUNT</span>(*) <span class="cq-kw">FROM</span> enrollments <span class="cq-kw">WHERE</span> students.id = enrollments.student_id</span>) <span class="cq-kw">AS</span> course_count
<span class="cq-kw">FROM</span> students;</div>
</div>
<div class="cq-src-row">
<div class="cq-src-col">
<p class="cq-table-name">students</p>
<div class="cq-table-scroll"><table class="cq-table" id="cqStudentsTable"><thead><tr><th>id</th><th>name</th></tr></thead><tbody></tbody></table></div>
</div>
<div class="cq-src-col">
<p class="cq-table-name">enrollments</p>
<div class="cq-table-scroll"><table class="cq-table" id="cqEnrollTable"><thead><tr><th>student_id</th><th>course</th></tr></thead><tbody></tbody></table></div>
</div>
</div>
<div class="cq-run-row">
<button class="cq-run-btn" id="cqSetupBtn" type="button">▶ Run Setup</button>
<button class="cq-run-btn" id="cqRunBtn" type="button" disabled>▶ Run the query</button>
<button class="cq-run-btn is-secondary" id="cqReset" type="button">↺ Reset</button>
</div>
<div class="cq-log-scroll">
<div class="cq-log" id="cqLog"><span class="cq-log-placeholder">Run Setup, then run the query to see the subquery re-run for every row...</span></div>
</div>
<p class="cq-result-label" id="cqResultLabel">Query Result</p>
<div class="cq-result-scroll" id="cqResultScroll">
<table class="cq-result-table" id="cqResultTable"><thead><tr><th>name</th><th>course_count</th></tr></thead><tbody id="cqResultBody"></tbody></table>
</div>
</div>
</div>
<script>
(function () {
const wrapper = document.getElementById('correlatedrunner');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') {
dark = true;
} else if (bodyAttr === 'false') {
dark = false;
} else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
})();
(function () {
const students = [{ id: 1, name: 'Anya' }, { id: 2, name: 'Raj' }, { id: 3, name: 'Sara' }];
const enrollments = [{ student_id: 1, course: 'Math' }, { student_id: 1, course: 'Science' }, { student_id: 2, course: 'Math' }];
const studentsTbody = document.querySelector('#cqStudentsTable tbody');
const enrollTbody = document.querySelector('#cqEnrollTable tbody');
const setupBtn = document.getElementById('cqSetupBtn');
const runBtn = document.getElementById('cqRunBtn');
const log = document.getElementById('cqLog');
const resultLabel = document.getElementById('cqResultLabel');
const resultScroll = document.getElementById('cqResultScroll');
const resultBody = document.getElementById('cqResultBody');
function clearLog() { log.innerHTML = ''; }
function appendLog(text, heading) {
if (log.querySelector('.cq-log-placeholder')) log.innerHTML = '';
const line = document.createElement('div');
line.className = 'cq-log-line' + (heading ? ' is-heading' : '');
line.textContent = text;
log.appendChild(line);
}
function delay(ms) { return new Promise(res => setTimeout(res, ms)); }
function renderSource() {
studentsTbody.innerHTML = students.map(s => '<tr data-id="' + s.id + '"><td>' + s.id + '</td><td>' + s.name + '</td></tr>').join('');
enrollTbody.innerHTML = enrollments.map((e, i) => '<tr data-idx="' + i + '" data-sid="' + e.student_id + '"><td>' + e.student_id + '</td><td>' + e.course + '</td></tr>').join('');
}
setupBtn.addEventListener('click', () => {
setupBtn.disabled = true;
renderSource();
runBtn.disabled = false;
appendLog('Both tables created, all sample data inserted.');
});
runBtn.addEventListener('click', async () => {
runBtn.disabled = true;
clearLog();
resultLabel.classList.remove('is-visible');
resultScroll.classList.remove('is-visible');
resultBody.innerHTML = '';
studentsTbody.querySelectorAll('tr').forEach(tr => tr.classList.remove('is-outer-current'));
enrollTbody.querySelectorAll('tr').forEach(tr => tr.classList.remove('is-inner-checking', 'is-inner-match'));
appendLog('This subquery is correlated — it references students.id, so it must re-run once for every outer row.');
await delay(500);
const results = [];
for (const s of students) {
const outerTr = studentsTbody.querySelector('tr[data-id="' + s.id + '"]');
studentsTbody.querySelectorAll('tr').forEach(t => t.classList.remove('is-outer-current'));
outerTr.classList.add('is-outer-current');
appendLog('Outer row: ' + s.name + ' (id=' + s.id + ')', true);
await delay(350);
appendLog(' Running: SELECT COUNT(*) FROM enrollments WHERE student_id = ' + s.id);
await delay(300);
let count = 0;
for (let i = 0; i < enrollments.length; i++) {
const e = enrollments[i];
const innerTr = enrollTbody.querySelector('tr[data-idx="' + i + '"]');
enrollTbody.querySelectorAll('tr').forEach(t => t.classList.remove('is-inner-checking'));
innerTr.classList.add('is-inner-checking');
const isMatch = e.student_id === s.id;
await delay(160);
innerTr.classList.remove('is-inner-checking');
if (isMatch) { innerTr.classList.add('is-inner-match'); count++; }
}
appendLog(' → course_count = ' + count);
results.push([s.name, count]);
await delay(300);
enrollTbody.querySelectorAll('tr').forEach(t => t.classList.remove('is-inner-match'));
}
studentsTbody.querySelectorAll('tr').forEach(t => t.classList.remove('is-outer-current'));
appendLog('3 rows returned — one per student, each with its own freshly computed count.', true);
resultBody.innerHTML = results.map(r => '<tr class="is-new"><td>' + r[0] + '</td><td>' + r[1] + '</td></tr>').join('');
resultLabel.classList.add('is-visible');
resultScroll.classList.add('is-visible');
resultScroll.scrollIntoView({ behavior: 'smooth', block: 'center' });
runBtn.disabled = false;
});
document.getElementById('cqReset').addEventListener('click', () => {
studentsTbody.innerHTML = '';
enrollTbody.innerHTML = '';
clearLog();
log.innerHTML = '<span class="cq-log-placeholder">Run Setup, then run the query to see the subquery re-run for every row...</span>';
resultLabel.classList.remove('is-visible');
resultScroll.classList.remove('is-visible');
resultBody.innerHTML = '';
setupBtn.disabled = false;
runBtn.disabled = true;
});
})();
</script>
</body>
</html>.demo {
font-family: system-ui, sans-serif;
padding: 16px;
}
.demo h1 {
color: #2563eb;
margin: 0 0 8px;
}
.demo p {
color: #4b5563;
margin: 0;
}document.querySelector('.demo h1')?.addEventListener('click', () => {
alert('Hello from live preview!');
});✔️ Shows each student with their number of courses
🧩 Types of Subqueries
Type | Location | Returns | Example Keyword |
|---|---|---|---|
🧮 Scalar Subquery |
| Single value |
|
📃 Multi-row Subquery |
| Multiple rows |
|
🧾 Correlated Subquery |
| Varies (uses outer row) | (See below) |
📦 Inline View ( |
| Table-like result | Used as virtual table |
🔁 Correlated Subquery (Dynamic per row)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Correlated Subquery — Above Section Average</title>
<style>
.infographic-sectionavgrunner {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--good: #16a34a;
--good-soft: #dcfce7;
--bad: #dc2626;
--bad-soft: #fee2e2;
--on-accent: #ffffff;
--display-font: Georgia, 'Iowan Old Style', serif;
--body-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
--mono-font: 'SF Mono', Consolas, monospace;
background: var(--paper);
color: var(--ink);
font-family: var(--body-font);
max-width: 780px;
margin: 0 auto;
box-sizing: border-box;
overflow-x: hidden;
}
.infographic-sectionavgrunner[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
--good: #4ade80;
--good-soft: #123420;
--bad: #f87171;
--bad-soft: #3a1414;
--on-accent: #101418;
}
.infographic-sectionavgrunner * { box-sizing: border-box; }
.sa-frame { background: var(--paper-alt); border: 1px solid var(--line); border-radius: 10px; padding: 1.25rem; }
.sa-kw { color: #9cc5ff; } .sa-str { color: #f8d980; } .sa-num { color: #4ade80; }
.sa-inner { text-decoration: underline; text-decoration-color: var(--accent); text-decoration-thickness: 2px; }
.sa-code-scroll { overflow-x: auto; }
.sa-code {
background: var(--ink); color: #d4e2ff; border-radius: 8px; padding: 0.9rem 1.1rem;
font-family: var(--mono-font); font-size: 0.8rem; line-height: 1.6; white-space: pre;
display: inline-block;
min-width: 100%;
}
.infographic-sectionavgrunner[data-theme="dark"] .sa-code { background: #05070a; }
.sa-table-name { font-size: 0.72rem; color: var(--ink-soft); text-transform: uppercase; letter-spacing: 0.04em; margin: 1.1rem 0 0.4rem; }
.sa-table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; min-width: 0; }
table.sa-table {
width: 100%; min-width: 300px; border-collapse: collapse; background: var(--paper);
border-radius: 8px; font-size: 0.88rem;
}
table.sa-table th, table.sa-table td {
border: 1px solid var(--line); padding: 0.5rem 0.7rem; text-align: left; white-space: nowrap;
transition: background 0.4s, color 0.4s;
}
table.sa-table th { background: var(--accent); color: var(--on-accent); font-weight: 700; font-size: 0.75rem; }
table.sa-table tr.is-outer-current td { background: var(--accent-soft); }
table.sa-table tr.is-peer td { background: var(--good-soft); }
table.sa-table tr.is-above td { color: var(--good); font-weight: 700; }
table.sa-table tr.is-below td { color: var(--ink-soft); }
.sa-run-row { display: flex; justify-content: center; gap: 0.6rem; margin-top: 1.1rem; flex-wrap: wrap; }
.sa-run-btn {
font: inherit; font-size: 0.85rem; background: var(--accent); color: var(--on-accent);
border: none; border-radius: 7px; padding: 0.6rem 1.2rem; cursor: pointer;
}
.sa-run-btn:hover { opacity: 0.9; }
.sa-run-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.sa-run-btn.is-secondary { background: var(--paper); color: var(--ink); border: 1px solid var(--line); }
.sa-log-scroll { overflow-x: auto; margin-top: 1.1rem; }
.sa-log {
background: var(--ink); color: #d4e2ff; border-radius: 8px; padding: 0.75rem 0.9rem;
font-family: var(--mono-font); font-size: 0.76rem; line-height: 1.6; min-height: 1.5rem;
}
.infographic-sectionavgrunner[data-theme="dark"] .sa-log { background: #05070a; }
.sa-log-line { opacity: 0; animation: sa-line-in 0.25s ease forwards; }
.sa-log-line.is-heading { color: #93c5fd; font-weight: 700; margin-top: 0.4rem; }
.sa-log-line.is-good { color: #86efac; }
.sa-log-line.is-bad { color: #fca5a5; }
@keyframes sa-line-in { to { opacity: 1; } }
.sa-log-placeholder { color: #7c8aa8; font-style: italic; }
.sa-result-label { font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-soft); margin: 1.1rem 0 0.6rem; display: none; }
.sa-result-label.is-visible { display: block; }
.sa-result-scroll { overflow-x: auto; display: none; }
.sa-result-scroll.is-visible { display: block; }
table.sa-result-table {
width: 100%; min-width: 140px; border-collapse: collapse; background: var(--paper);
border-radius: 8px; font-size: 0.88rem;
}
table.sa-result-table th, table.sa-result-table td {
border: 1px solid var(--line); padding: 0.5rem 0.7rem; text-align: left; white-space: nowrap;
}
table.sa-result-table th { background: var(--good); color: #fff; font-weight: 700; font-size: 0.75rem; }
table.sa-result-table tr.is-new td { animation: sa-row-in 0.5s ease; }
@keyframes sa-row-in { from { background: var(--good-soft); } to { background: transparent; } }
@media (prefers-reduced-motion: reduce) {
.infographic-sectionavgrunner *, .infographic-sectionavgrunner *::before, .infographic-sectionavgrunner *::after {
transition-duration: 0.001ms !important; animation-duration: 0.001ms !important;
}
}
</style>
</head>
<body>
<div class="infographic-sectionavgrunner" id="sectionavgrunner">
<div class="sa-frame">
<div class="sa-code-scroll">
<div class="sa-code"><span class="sa-kw">CREATE TABLE</span> students (
id <span class="sa-kw">INT AUTO_INCREMENT PRIMARY KEY</span>,
name <span class="sa-kw">VARCHAR</span>(50),
marks <span class="sa-kw">INT</span>,
section <span class="sa-kw">VARCHAR</span>(1)
);
<span class="sa-kw">INSERT INTO</span> students (name, marks, section) <span class="sa-kw">VALUES</span>
(<span class="sa-str">'Anya'</span>, <span class="sa-num">85</span>, <span class="sa-str">'A'</span>),
(<span class="sa-str">'Raj'</span>, <span class="sa-num">70</span>, <span class="sa-str">'A'</span>),
(<span class="sa-str">'Sara'</span>, <span class="sa-num">95</span>, <span class="sa-str">'A'</span>),
(<span class="sa-str">'Ravi'</span>, <span class="sa-num">65</span>, <span class="sa-str">'B'</span>),
(<span class="sa-str">'Tina'</span>, <span class="sa-num">90</span>, <span class="sa-str">'B'</span>);
<span class="sa-kw">SELECT</span> name
<span class="sa-kw">FROM</span> students s
<span class="sa-kw">WHERE</span> marks > (
<span class="sa-inner"><span class="sa-kw">SELECT</span> <span class="sa-kw">AVG</span>(marks)
<span class="sa-kw">FROM</span> students
<span class="sa-kw">WHERE</span> section = s.section</span>
);</div>
</div>
<p class="sa-table-name">students</p>
<div class="sa-table-scroll">
<table class="sa-table" id="saTable">
<thead><tr><th>id</th><th>name</th><th>marks</th><th>section</th></tr></thead>
<tbody></tbody>
</table>
</div>
<div class="sa-run-row">
<button class="sa-run-btn" id="saSetupBtn" type="button">▶ Run Setup</button>
<button class="sa-run-btn" id="saRunBtn" type="button" disabled>▶ Run the query</button>
<button class="sa-run-btn is-secondary" id="saReset" type="button">↺ Reset</button>
</div>
<div class="sa-log-scroll">
<div class="sa-log" id="saLog"><span class="sa-log-placeholder">Run Setup, then run the query to see each student compared against their own section...</span></div>
</div>
<p class="sa-result-label" id="saResultLabel">Query Result</p>
<div class="sa-result-scroll" id="saResultScroll">
<table class="sa-result-table" id="saResultTable"><thead><tr><th>name</th></tr></thead><tbody id="saResultBody"></tbody></table>
</div>
</div>
</div>
<script>
(function () {
const wrapper = document.getElementById('sectionavgrunner');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') {
dark = true;
} else if (bodyAttr === 'false') {
dark = false;
} else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
})();
(function () {
const students = [
{ id: 1, name: 'Anya', marks: 85, section: 'A' },
{ id: 2, name: 'Raj', marks: 70, section: 'A' },
{ id: 3, name: 'Sara', marks: 95, section: 'A' },
{ id: 4, name: 'Ravi', marks: 65, section: 'B' },
{ id: 5, name: 'Tina', marks: 90, section: 'B' }
];
const table = document.getElementById('saTable');
const tbody = table.querySelector('tbody');
const setupBtn = document.getElementById('saSetupBtn');
const runBtn = document.getElementById('saRunBtn');
const log = document.getElementById('saLog');
const resultLabel = document.getElementById('saResultLabel');
const resultScroll = document.getElementById('saResultScroll');
const resultBody = document.getElementById('saResultBody');
function clearLog() { log.innerHTML = ''; }
function appendLog(text, cls) {
if (log.querySelector('.sa-log-placeholder')) log.innerHTML = '';
const line = document.createElement('div');
line.className = 'sa-log-line' + (cls ? ' ' + cls : '');
line.textContent = text;
log.appendChild(line);
}
function delay(ms) { return new Promise(res => setTimeout(res, ms)); }
function renderStudents() {
tbody.innerHTML = students.map(s =>
'<tr data-id="' + s.id + '"><td>' + s.id + '</td><td>' + s.name + '</td><td>' + s.marks + '</td><td>' + s.section + '</td></tr>'
).join('');
}
setupBtn.addEventListener('click', () => {
setupBtn.disabled = true;
renderStudents();
runBtn.disabled = false;
appendLog('Table created, 5 rows inserted.');
});
runBtn.addEventListener('click', async () => {
runBtn.disabled = true;
clearLog();
resultLabel.classList.remove('is-visible');
resultScroll.classList.remove('is-visible');
resultBody.innerHTML = '';
tbody.querySelectorAll('tr').forEach(tr => tr.classList.remove('is-outer-current', 'is-peer', 'is-above', 'is-below'));
appendLog('Correlated subquery: WHERE section = s.section — must re-run once per outer row, using that row\u2019s own section.');
await delay(500);
const matches = [];
for (const s of students) {
const outerTr = tbody.querySelector('tr[data-id="' + s.id + '"]');
tbody.querySelectorAll('tr').forEach(t => t.classList.remove('is-outer-current', 'is-peer'));
outerTr.classList.add('is-outer-current');
appendLog('Outer row: ' + s.name + ' (marks=' + s.marks + ', section=' + s.section + ')', 'is-heading');
await delay(320);
appendLog(" Running: SELECT AVG(marks) FROM students WHERE section = '" + s.section + "'");
await delay(280);
const peers = students.filter(st => st.section === s.section);
let sum = 0;
for (const p of peers) {
const peerTr = tbody.querySelector('tr[data-id="' + p.id + '"]');
peerTr.classList.add('is-peer');
sum += p.marks;
await delay(160);
}
const avg = Math.round((sum / peers.length) * 100) / 100;
appendLog(' Section ' + s.section + ' average = ' + avg);
await delay(300);
const isAbove = s.marks > avg;
appendLog(' ' + s.marks + (isAbove ? ' > ' : ' \u2264 ') + avg + ' → ' + (isAbove ? 'INCLUDED' : 'excluded'), isAbove ? 'is-good' : 'is-bad');
outerTr.classList.remove('is-outer-current');
outerTr.classList.add(isAbove ? 'is-above' : 'is-below');
tbody.querySelectorAll('tr').forEach(t => t.classList.remove('is-peer'));
if (isAbove) matches.push(s.name);
await delay(250);
}
appendLog(matches.length + ' row(s) returned: ' + matches.join(', '), 'is-heading');
resultBody.innerHTML = matches.map(n => '<tr class="is-new"><td>' + n + '</td></tr>').join('');
resultLabel.classList.add('is-visible');
resultScroll.classList.add('is-visible');
resultScroll.scrollIntoView({ behavior: 'smooth', block: 'center' });
runBtn.disabled = false;
});
document.getElementById('saReset').addEventListener('click', () => {
tbody.innerHTML = '';
clearLog();
log.innerHTML = '<span class="sa-log-placeholder">Run Setup, then run the query to see each student compared against their own section...</span>';
resultLabel.classList.remove('is-visible');
resultScroll.classList.remove('is-visible');
resultBody.innerHTML = '';
setupBtn.disabled = false;
runBtn.disabled = true;
});
})();
</script>
</body>
</html>.demo {
font-family: system-ui, sans-serif;
padding: 16px;
}
.demo h1 {
color: #2563eb;
margin: 0 0 8px;
}
.demo p {
color: #4b5563;
margin: 0;
}document.querySelector('.demo h1')?.addEventListener('click', () => {
alert('Hello from live preview!');
});✔️ Compares each student's marks to average of their own section
✅ Summary
Subquery Location | Common Use | Keyword Examples |
|---|---|---|
| Compare values or lists |
|
| Treat as temporary table |
|
| Add computed columns |
|
Correlated | Compare using outer query data | Dynamic per row |