{"id":1176,"date":"2026-10-17T21:33:00","date_gmt":"2026-10-17T16:03:00","guid":{"rendered":"https:\/\/codeanddebug.in\/blog\/?p=1176"},"modified":"2026-10-17T21:33:02","modified_gmt":"2026-10-17T16:03:02","slug":"sql-interview-questions","status":"publish","type":"post","link":"https:\/\/codeanddebug.in\/blog\/sql-interview-questions\/","title":{"rendered":"100 SQL Interview Questions with Queries and Answers (Freshers to Experienced)"},"content":{"rendered":"\n<style>.cdai{--cd-brand:#3c3fde;--cd-brand-soft:#eceeff;--cd-ink:#14162b;--cd-muted:#5b5f7a;--cd-line:#dfe1ee;--cd-card:#ffffff;--cd-bg:#f6f7fc;--cd-good:#0f8a5f;--cd-good-soft:#e3f6ee;--cd-bad:#c2410c;--cd-bad-soft:#fdebe1;--cd-warn:#b7791f;--cd-on-brand:#ffffff;\nfont-family:Inter,system-ui,-apple-system,\"Segoe UI\",Roboto,sans-serif;color:var(--cd-ink);background:var(--cd-bg);border:1px solid var(--cd-line);border-radius:14px;padding:22px;margin:28px 0;line-height:1.55;font-size:16px;box-sizing:border-box;max-width:100%;overflow:hidden}\n.s-dark .cdai,.cdai.cd-dark{--cd-brand:#8d90ff;--cd-brand-soft:#23254a;--cd-ink:#e8e9f5;--cd-muted:#a3a6c2;--cd-line:#32354f;--cd-card:#1b1d33;--cd-bg:#14162a;--cd-good:#4ccf98;--cd-good-soft:#163a2c;--cd-bad:#ff9a6b;--cd-bad-soft:#3d2316;--cd-warn:#f2c46b;--cd-on-brand:#0f1030}\n.cdai *,.cdai *::before,.cdai *::after{box-sizing:border-box}\n.cdai h4.cd-h{font-family:Outfit,Inter,sans-serif;font-size:1.25rem;font-weight:700;margin:0 0 4px;color:var(--cd-ink);line-height:1.3}\n.cdai .cd-sub{color:var(--cd-muted);font-size:.95rem;margin:0 0 16px}\n.cdai .cd-tag{display:inline-block;font-size:.72rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--cd-brand);background:var(--cd-brand-soft);padding:3px 9px;border-radius:99px;margin-bottom:10px}\n.cdai button.cd-btn,.cdai .cd-chip{font:inherit;font-size:.92rem;font-weight:600;cursor:pointer;border-radius:10px;border:1.5px solid var(--cd-line);background:var(--cd-card);color:var(--cd-ink);padding:9px 14px;line-height:1.3;transition:transform .15s ease,border-color .15s ease,background .15s ease;text-transform:none;letter-spacing:normal;box-shadow:none;margin:0;min-height:0;height:auto}\n.cdai button.cd-btn:hover,.cdai .cd-chip:hover{border-color:var(--cd-brand);transform:translateY(-1px)}\n.cdai button.cd-btn:focus-visible,.cdai .cd-chip:focus-visible,.cdai input:focus-visible{outline:3px solid var(--cd-brand);outline-offset:2px}\n.cdai .cd-primary,.cdai button.cd-primary{background:var(--cd-brand);border-color:var(--cd-brand);color:var(--cd-on-brand)}\n.cdai .cd-chip[aria-pressed=\"true\"]{background:var(--cd-brand);border-color:var(--cd-brand);color:var(--cd-on-brand)}\n.cdai .cd-row{display:flex;flex-wrap:wrap;gap:10px;align-items:center}\n.cdai .cd-grid2{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,230px),1fr));gap:12px}\n.cdai .cd-card{background:var(--cd-card);border:1px solid var(--cd-line);border-radius:12px;padding:14px}\n.cdai .cd-stat{font-family:Outfit,Inter,sans-serif;font-size:2rem;font-weight:700;color:var(--cd-brand);line-height:1.1;font-variant-numeric:tabular-nums}\n.cdai .cd-small{font-size:.85rem;color:var(--cd-muted)}\n.cdai label.cd-lab{font-weight:600;font-size:.92rem;display:flex;justify-content:space-between;gap:10px;margin:14px 0 6px}\n.cdai input[type=range]{width:100%;accent-color:var(--cd-brand);margin:0;height:28px;background:transparent;border:0;padding:0}\n.cdai canvas{display:block;width:100%;height:auto;border-radius:10px;background:var(--cd-card);border:1px solid var(--cd-line);touch-action:pan-y}\n\/* hero *\/\n.cdai.cd-hero{padding:0;position:relative;background:#101233;border-color:#24275a}\n.cdai.cd-hero canvas{border:0;border-radius:0;background:transparent;height:200px}\n.cdai.cd-hero .cd-hero-txt{position:absolute;left:0;right:0;bottom:0;padding:16px 20px;background:linear-gradient(transparent,rgba(16,18,51,.92) 55%);color:#fff}\n.cdai.cd-hero .cd-hero-txt b{font-family:Outfit,Inter,sans-serif;font-size:1.15rem}\n.cdai.cd-hero .cd-hero-txt span{display:block;color:#c9cbff;font-size:.9rem}\n\/* planner *\/\n.cdai .cd-timeline{display:flex;flex-direction:column;gap:7px;margin-top:6px}\n.cdai .cd-tl-row{display:grid;grid-template-columns:minmax(0,150px) 1fr 62px;gap:10px;align-items:center;font-size:.88rem}\n.cdai .cd-tl-name{font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.cdai .cd-tl-name a{color:inherit;text-decoration:none}\n.cdai .cd-tl-name a:hover{color:var(--cd-brand)}\n.cdai .cd-tl-track{height:14px;background:var(--cd-brand-soft);border-radius:99px;overflow:hidden}\n.cdai .cd-tl-bar{height:100%;background:var(--cd-brand);border-radius:99px;width:0;transition:width .6s cubic-bezier(.2,.8,.2,1)}\n.cdai .cd-tl-bar.cd-skim{background:repeating-linear-gradient(45deg,var(--cd-brand),var(--cd-brand) 6px,transparent 6px,transparent 10px)}\n.cdai .cd-tl-w{text-align:right;font-variant-numeric:tabular-nums;color:var(--cd-muted)}\n.cdai .cd-prog{height:10px;border-radius:99px;background:var(--cd-brand-soft);overflow:hidden;margin-top:8px}\n.cdai .cd-prog i{display:block;height:100%;background:var(--cd-good);width:0;transition:width .4s ease}\n@media (max-width:520px){.cdai{padding:16px}.cdai .cd-tl-row{grid-template-columns:minmax(0,110px) 1fr 50px;font-size:.8rem}}\n\/* game *\/\n.cdai .cd-game-card{background:var(--cd-card);border:1px solid var(--cd-line);border-radius:12px;padding:18px;min-height:96px;font-size:1.05rem;font-weight:600;display:flex;align-items:center}\n.cdai .cd-feedback{margin-top:12px;padding:12px 14px;border-radius:10px;font-size:.93rem}\n.cdai .cd-feedback.cd-ok{background:var(--cd-good-soft);color:var(--cd-ink);border-left:4px solid var(--cd-good)}\n.cdai .cd-feedback.cd-no{background:var(--cd-bad-soft);color:var(--cd-ink);border-left:4px solid var(--cd-bad)}\n.cdai .cd-venn{position:relative;width:min(100%,300px);aspect-ratio:1\/1;margin:6px auto 0}\n.cdai .cd-venn div{position:absolute;border-radius:50%;border:2px solid var(--cd-brand);display:flex;justify-content:center;font-weight:700;font-size:.8rem;color:var(--cd-ink);padding-top:6px;transition:background .3s ease,transform .3s ease}\n.cdai .cd-venn div.cd-lit{background:var(--cd-brand-soft);transform:scale(1.03)}\n.cdai .cd-v1{inset:0}.cdai .cd-v2{inset:12%}.cdai .cd-v3{inset:26%}.cdai .cd-v4{inset:40%;align-items:center;padding-top:0!important}\n\/* checklist *\/\n.cdai.cd-check{padding:16px 18px;background:var(--cd-card)}\n.cdai.cd-check ul{list-style:none;margin:8px 0 0;padding:0}\n.cdai.cd-check li{margin:0;padding:0}\n.cdai.cd-check label{display:flex;gap:10px;align-items:flex-start;padding:7px 4px;cursor:pointer;font-size:.95rem;border-radius:8px}\n.cdai.cd-check label:hover{background:var(--cd-bg)}\n.cdai.cd-check input{width:18px;height:18px;margin-top:3px;accent-color:var(--cd-good);flex:none}\n.cdai.cd-check .cd-done{color:var(--cd-good);font-weight:700}\n\/* tokens *\/\n.cdai .cd-bars{display:flex;flex-direction:column;gap:6px;margin-top:10px}\n.cdai .cd-bar-row{display:grid;grid-template-columns:110px 1fr 52px;gap:10px;align-items:center;font-size:.9rem}\n.cdai .cd-bar-row b{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-weight:600}\n.cdai .cd-bar-row .cd-tl-bar{transition:width .35s ease}\n.cdai .cd-out{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;background:var(--cd-card);border:1px solid var(--cd-line);border-radius:10px;padding:12px;margin-top:12px;min-height:46px;font-size:.92rem;word-break:break-word}\n.cdai .cd-out mark{background:var(--cd-brand-soft);color:var(--cd-brand);padding:1px 4px;border-radius:4px;animation:cdpop .4s ease}\n@keyframes cdpop{from{transform:scale(1.4);opacity:0}to{transform:none;opacity:1}}\n.cdai .cd-meter{font-family:Outfit,Inter,sans-serif;font-weight:700;font-size:1.6rem;font-variant-numeric:tabular-nums}\n@media (prefers-reduced-motion:reduce){.cdai *{transition:none!important;animation:none!important}}\n.cdai .cd-tbl-wrap{overflow-x:auto;margin-top:10px}\n.cdai table.cd-tbl{border-collapse:collapse;width:100%;font-size:.88rem;font-variant-numeric:tabular-nums;background:var(--cd-card);margin:0}\n.cdai table.cd-tbl th,.cdai table.cd-tbl td{border:1px solid var(--cd-line);padding:6px 8px;text-align:center;color:var(--cd-ink)}\n.cdai table.cd-tbl th{background:var(--cd-brand-soft);font-weight:700;font-size:.8rem}\n.cdai table.cd-tbl input{width:64px;font:inherit;padding:4px 6px;border:1.5px solid var(--cd-line);border-radius:6px;background:var(--cd-bg);color:var(--cd-ink);text-align:center;margin:0}\n.cdai .cd-steps{margin-top:12px;display:grid;gap:6px;font-size:.92rem}\n.cdai .cd-steps div{background:var(--cd-card);border:1px solid var(--cd-line);border-radius:8px;padding:8px 12px}\n.cdai .cd-steps code,.cdai .cd-eq{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:.9rem;background:transparent;color:var(--cd-ink);padding:0}\n.cdai .cd-eq{display:inline-block;background:var(--cd-brand-soft);color:var(--cd-brand);padding:4px 10px;border-radius:8px;font-weight:700}\n.cdai.cd-codebox{padding:0;background:#16182c;border-color:#2a2d48}\n.cdai.cd-codebox .cd-codehead{display:flex;justify-content:space-between;align-items:center;padding:8px 14px;border-bottom:1px solid #2a2d48;color:#a3a6c2;font-size:.8rem;font-weight:600}\n.cdai.cd-codebox pre{margin:0;padding:14px 16px;overflow-x:auto;background:transparent;border:0;color:#e6e7f2;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:.86rem;line-height:1.6;white-space:pre}\n.cdai.cd-codebox pre code{background:transparent;color:inherit;padding:0;font:inherit}\n.cdai.cd-codebox .cd-copy{font:inherit;font-size:.78rem;font-weight:600;cursor:pointer;background:#2a2d48;color:#e6e7f2;border:0;border-radius:6px;padding:5px 10px;margin:0;text-transform:none;letter-spacing:normal}\n.cdai.cd-codebox .cd-outp{border-top:1px dashed #2a2d48;color:#8fe3b8}\n.cdai .cd-legend{display:flex;flex-wrap:wrap;gap:14px;font-size:.82rem;color:var(--cd-muted);margin-top:8px}\n.cdai .cd-legend i{display:inline-block;width:10px;height:10px;border-radius:50%;margin-right:5px;vertical-align:middle}\n.cdai canvas.cd-touch{touch-action:none;cursor:crosshair}\n.cdai canvas.cd-grab{touch-action:none;cursor:grab}\n.cdai .cd-q-opts{display:grid;gap:8px;margin-top:12px}\n.cdai .cd-q-opts button.cd-btn{text-align:left;width:100%}\n.cdai .cd-q-opts button.cd-right{border-color:var(--cd-good);background:var(--cd-good-soft)}\n.cdai .cd-q-opts button.cd-wrong{border-color:var(--cd-bad);background:var(--cd-bad-soft)}\n.cdai .cd-odds-dots{display:grid;grid-template-columns:repeat(10,1fr);gap:6px;max-width:320px;margin-top:10px}\n.cdai .cd-odds-dots i{display:block;aspect-ratio:1\/1;border-radius:50%;background:var(--cd-line);transition:background .25s ease}\n.cdai .cd-cm{display:grid;grid-template-columns:auto 1fr 1fr;gap:6px;font-size:.88rem;max-width:420px;margin-top:12px}\n.cdai .cd-cm div{padding:10px 8px;border-radius:8px;text-align:center}\n.cdai .cd-cm .cd-cm-h{color:var(--cd-muted);font-weight:600;font-size:.78rem;align-self:center}\n.cdai .cd-cm .cd-cm-c{background:var(--cd-card);border:1px solid var(--cd-line)}\n.cdai .cd-cm .cd-cm-c b{display:block;font-family:Outfit,Inter,sans-serif;font-size:1.5rem;font-variant-numeric:tabular-nums}\n.cdai .cd-cm .cd-cm-good{border-color:var(--cd-good);background:var(--cd-good-soft)}\n.cdai .cd-cm .cd-cm-bad{border-color:var(--cd-bad);background:var(--cd-bad-soft)}\n.cdai.cd-q{background:var(--cd-card);padding:18px 20px;margin:18px 0;border-left:4px solid var(--cd-brand)}\n.cdai.cd-q[hidden]{display:none!important}\n.cdai.cd-q.cd-is-known{border-left-color:var(--cd-good)}\n.cdai.cd-q .cd-q-meta{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:6px}\n.cdai .cd-pill{font-size:.72rem;font-weight:700;padding:3px 9px;border-radius:99px;background:var(--cd-brand-soft);color:var(--cd-brand);letter-spacing:.02em}\n.cdai .cd-pill.cd-lv-Freshers{background:var(--cd-good-soft);color:var(--cd-good)}\n.cdai .cd-pill.cd-lv-Experienced{background:var(--cd-bad-soft);color:var(--cd-bad)}\n.cdai.cd-q h3.cd-q-title{font-family:Outfit,Inter,sans-serif;font-size:1.15rem;line-height:1.35;margin:4px 0 10px;color:var(--cd-ink)}\n.cdai.cd-q .cd-q-body{font-size:.97rem}\n.cdai.cd-q .cd-q-body p{margin:0 0 10px}\n.cdai.cd-q .cd-q-body ul,.cdai.cd-q .cd-q-body ol{margin:0 0 10px 1.2em;padding:0}\n.cdai.cd-q .cd-q-body li{margin:3px 0}\n.cdai.cd-q .cd-q-body code,.cdai.cd-fc .cd-fc-a code{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:.86em;background:var(--cd-brand-soft);color:var(--cd-ink);padding:1px 5px;border-radius:4px}\n.cdai.cd-q .cd-q-body pre code,.cdai.cd-fc .cd-fc-a pre code{background:transparent;color:inherit;padding:0;font-size:inherit}\n.cdai.cd-q .cd-q-body table,.cdai.cd-fc table{border-collapse:collapse;width:100%;font-size:.88rem;margin:6px 0 12px}\n.cdai.cd-q .cd-q-body th,.cdai.cd-q .cd-q-body td,.cdai.cd-fc th,.cdai.cd-fc td{border:1px solid var(--cd-line);padding:6px 8px;text-align:left;color:var(--cd-ink)}\n.cdai.cd-q .cd-q-body th,.cdai.cd-fc th{background:var(--cd-brand-soft)}\n.cdai.cd-q .cd-codebox,.cdai.cd-fc .cd-codebox{margin:12px 0 4px}\n.cdai.cd-q .cd-q-foot{display:flex;justify-content:space-between;align-items:center;gap:10px;margin-top:10px;flex-wrap:wrap}\n.cdai.cd-q .cd-known[aria-pressed=\"true\"]{background:var(--cd-good-soft);border-color:var(--cd-good);color:var(--cd-good)}\n.cdai.cd-q .cd-show{display:none}\n.cdai.cd-q.cd-practice:not(.cd-revealed) .cd-q-body{display:none}\n.cdai.cd-q.cd-practice:not(.cd-revealed) .cd-show{display:inline-block}\n.cdai .cd-q-top{font-size:.8rem;color:var(--cd-muted);text-decoration:none}\n.cdai.cd-pyq-tool .cd-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(110px,1fr));gap:10px;margin:12px 0}\n.cdai.cd-pyq-tool select,.cdai.cd-pyq-tool input[type=search]{font:inherit;font-size:.92rem;padding:9px 12px;border:1.5px solid var(--cd-line);border-radius:10px;background:var(--cd-card);color:var(--cd-ink);margin:0;min-width:0;width:100%;height:auto}\n.cdai.cd-pyq-tool .cd-filters{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:12px}\n@media (max-width:560px){.cdai.cd-pyq-tool .cd-filters{grid-template-columns:1fr}}\n.cdai.cd-pyq-tool label.cd-tog{display:flex;align-items:center;gap:8px;font-size:.9rem;cursor:pointer}\n.cdai.cd-pyq-tool label.cd-tog input{width:18px;height:18px;accent-color:var(--cd-brand);margin:0}\n.cdai a.cd-btn{display:inline-block;text-decoration:none}\n.cdai a.cd-dl{background:var(--cd-good);border-color:var(--cd-good);color:#fff}\n.cdai.cd-fc{position:fixed;inset:0;z-index:99999;background:rgba(10,12,30,.72);display:flex;align-items:center;justify-content:center;margin:0;border:0;border-radius:0;padding:max(12px,env(safe-area-inset-top,0px)) max(12px,env(safe-area-inset-right,0px)) max(12px,env(safe-area-inset-bottom,0px)) max(12px,env(safe-area-inset-left,0px))}\n.cdai.cd-fc[hidden]{display:none}\n.cdai.cd-fc .cd-fc-card{background:var(--cd-card);color:var(--cd-ink);border-radius:16px;padding:20px;width:min(720px,100%);max-height:100%;overflow-y:auto;box-shadow:0 20px 60px rgba(0,0,0,.35)}\n.cdai.cd-fc .cd-fc-meta{display:flex;gap:6px;margin:12px 0 6px}\n.cdai.cd-fc .cd-fc-q{font-family:Outfit,Inter,sans-serif;font-size:1.3rem;font-weight:700;line-height:1.35;margin-bottom:14px}\n.cdai.cd-fc .cd-fc-a{border-top:1px dashed var(--cd-line);padding-top:12px;margin-bottom:12px;font-size:.95rem}\n.cdai.cd-fc .cd-fc-a p{margin:0 0 10px}.cdai.cd-fc .cd-fc-a ul,.cdai.cd-fc .cd-fc-a ol{margin:0 0 10px 1.2em;padding:0}\n.cdai.cd-fc .cd-fc-actions{margin-top:6px}\n.cdai a.cd-btn{font:inherit;font-size:.92rem;font-weight:600;cursor:pointer;border-radius:10px;border:1.5px solid var(--cd-line);background:var(--cd-card);color:var(--cd-ink);padding:9px 14px;line-height:1.3;text-decoration:none;display:inline-block;transition:transform .15s ease,border-color .15s ease}\n.cdai a.cd-btn:hover{transform:translateY(-1px);border-color:var(--cd-brand)}\n.cdai a.cd-btn.cd-dl{background:#0f8a5f;border-color:#0f8a5f;color:#fff}\n.cdai a.cd-btn.cd-dl:hover{background:#0c7550}\n.cdai a.cd-btn:focus-visible{outline:3px solid var(--cd-brand);outline-offset:2px}\n.cdai.cd-codebox .cd-codehead .cd-acts{display:flex;gap:6px;flex-wrap:wrap}\n.cdai.cd-codebox .cd-run{font:inherit;font-size:.78rem;font-weight:700;cursor:pointer;background:#3c3fde;color:#fff;border:0;border-radius:6px;padding:5px 12px;margin:0;text-transform:none;letter-spacing:normal}\n.cdai.cd-codebox .cd-run:disabled{opacity:.7;cursor:wait}\n.cdai.cd-codebox .cd-edit,.cdai.cd-codebox .cd-reset{font:inherit;font-size:.78rem;font-weight:600;cursor:pointer;background:transparent;color:#c9cbff;border:1px solid #3a3d5c;border-radius:6px;padding:4px 10px;margin:0;text-transform:none;letter-spacing:normal}\n.cdai.cd-codebox.cd-editing pre:first-of-type{outline:2px dashed #8d90ff;outline-offset:-6px}\n.cdai.cd-codebox pre code[contenteditable=\"true\"]{display:block;outline:none;caret-color:#fff}\n.cdai.cd-codebox .cd-live{background:var(--cd-card);color:var(--cd-ink);padding:12px 14px;border-top:1px solid #2a2d48}\n.cdai.cd-codebox .cd-live-head{font-size:.78rem;font-weight:700;color:var(--cd-good);margin-bottom:8px}\n.cdai.cd-codebox .cd-live-head span{font-weight:500;color:var(--cd-muted);margin-left:6px}\n.cdai .cd-sql-err{background:var(--cd-bad-soft);color:var(--cd-ink);border-left:4px solid var(--cd-bad);padding:8px 12px;border-radius:6px;font-family:ui-monospace,Menlo,Consolas,monospace;font-size:.85rem;margin-bottom:8px}\n.cdai table.cd-res{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:.8rem}\n.cdai table.cd-res th,.cdai table.cd-res td{text-align:left;white-space:nowrap;padding:5px 9px}\n.cdai table.cd-res td.cd-null{color:var(--cd-muted);font-style:italic}\n.cdai.cd-sql-play textarea{width:100%;min-height:150px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:.88rem;line-height:1.55;padding:12px;border-radius:10px;border:1.5px solid var(--cd-line);background:#16182c;color:#e6e7f2;resize:vertical;margin:0;box-sizing:border-box}\n.cdai.cd-sql-play .cd-play-out{margin-top:12px;background:var(--cd-card);border:1px solid var(--cd-line);border-radius:10px;padding:12px}\n.cdai .cd-schema{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,210px),1fr));gap:10px;margin:10px 0 14px}\n.cdai .cd-schema .cd-card b{font-family:ui-monospace,Menlo,Consolas,monospace;color:var(--cd-brand)}\n.cdai .cd-schema .cd-card code{font-size:.78rem;color:var(--cd-muted);background:transparent;padding:0;line-height:1.6;display:block}\n.cdai .cd-pill.cd-ty-Query{background:#fff4e0;color:#9a5b00}\n.s-dark .cdai .cd-pill.cd-ty-Query{background:#3a2c12;color:#f2c46b}\n.cdai .cd-play-out .cd-live-head{font-size:.78rem;font-weight:700;color:var(--cd-good);margin-bottom:8px}\n.cdai .cd-play-out .cd-live-head span{font-weight:500;color:var(--cd-muted);margin-left:6px}\n<\/style>\n\n\n\n<p class=\"wp-block-paragraph\">SQL shows up in almost every tech interview in India: software developer, data analyst, data engineer, business analyst and QA roles all test it, from campus placements to senior positions. And the questions follow a pattern. Interviewers ask a few concepts (keys, joins, normalization, indexes, transactions), then hand you a table and ask you to write queries: second highest salary, duplicates, top N per group, running totals.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This page has the <strong>100 SQL interview questions<\/strong> that come up most, grouped into freshers, intermediate and experienced levels, with 66 hands-on query questions and 34 concept questions. Every query uses one small sample database of employees, departments, customers and orders, so you can focus on the logic instead of a new schema each time. And you do not just read the queries: <strong>71 of them run live in your browser<\/strong>. Click Run, change the query, and run it again. Want an offline copy? <a href=\"https:\/\/codeanddebug.in\/blog\/wp-content\/uploads\/2026\/10\/sql-interview-questions-code-and-debug.pdf\">Download all 100 questions as a free PDF<\/a>.<\/p>\n\n\n\n<div class=\"cdai cd-pyq-tool\" id=\"cd-pyq-tool\">\n<span class=\"cd-tag\">Practice tools<\/span>\n<h4 class=\"cd-h\">Study these 100 SQL questions your way<\/h4>\n<p class=\"cd-sub\">Filter by level or question type, search, hide answers to test yourself, or switch to flashcards. Your progress is saved in this browser.<\/p>\n<div class=\"cd-stats\">\n<div class=\"cd-card\"><div class=\"cd-small\">Showing<\/div><div class=\"cd-stat\"><span class=\"cd-pyq-shown\">100<\/span><span style=\"font-size:1rem;color:var(--cd-muted)\"> \/ 100<\/span><\/div><\/div>\n<div class=\"cd-card\"><div class=\"cd-small\">You know<\/div><div class=\"cd-stat\"><span class=\"cd-pyq-known\">0<\/span><span style=\"font-size:1rem;color:var(--cd-muted)\"> \/ 100<\/span><\/div><div class=\"cd-prog cd-pyq-bar\"><i><\/i><\/div><\/div>\n<\/div>\n<div class=\"cd-row\" role=\"group\" aria-label=\"Level\">\n<button type=\"button\" class=\"cd-chip cd-lvl\" data-l=\"all\" aria-pressed=\"true\">All levels<\/button>\n<button type=\"button\" class=\"cd-chip cd-lvl\" data-l=\"Freshers\" aria-pressed=\"false\">Freshers (40)<\/button>\n<button type=\"button\" class=\"cd-chip cd-lvl\" data-l=\"Intermediate\" aria-pressed=\"false\">Intermediate (35)<\/button>\n<button type=\"button\" class=\"cd-chip cd-lvl\" data-l=\"Experienced\" aria-pressed=\"false\">Experienced (25)<\/button>\n<\/div>\n<div class=\"cd-row\" role=\"group\" aria-label=\"Question type\" style=\"margin-top:10px\">\n<button type=\"button\" class=\"cd-chip cd-typ\" data-t=\"all\" aria-pressed=\"true\">All types<\/button>\n<button type=\"button\" class=\"cd-chip cd-typ\" data-t=\"Query\" aria-pressed=\"false\">Query questions (66)<\/button>\n<button type=\"button\" class=\"cd-chip cd-typ\" data-t=\"Concept\" aria-pressed=\"false\">Concept questions (34)<\/button>\n<\/div>\n<div class=\"cd-filters\">\n<select class=\"cd-pyq-topic\" aria-label=\"Topic\"><option value=\"all\">All topics<\/option><\/select>\n<input type=\"search\" class=\"cd-pyq-search\" placeholder=\"Search, e.g. join, rank, null\" aria-label=\"Search questions\">\n<\/div>\n<div class=\"cd-row\" style=\"margin-top:12px;gap:18px\">\n<label class=\"cd-tog\"><input type=\"checkbox\" class=\"cd-pyq-practice\"> Practice mode (hide answers)<\/label>\n<label class=\"cd-tog\"><input type=\"checkbox\" class=\"cd-pyq-hideknown\"> Hide questions I know<\/label>\n<\/div>\n<div class=\"cd-row\" style=\"margin-top:14px\">\n<button type=\"button\" class=\"cd-btn cd-primary cd-pyq-fc\">Start flashcards<\/button>\n<a class=\"cd-btn cd-dl\" href=\"https:\/\/codeanddebug.in\/blog\/wp-content\/uploads\/2026\/10\/sql-interview-questions-code-and-debug.pdf\" download>Download PDF<\/a>\n<button type=\"button\" class=\"cd-btn cd-pyq-reset\">Reset progress<\/button>\n<\/div>\n<p class=\"cd-small cd-pyq-none\" hidden style=\"margin:12px 0 0\">No questions match these filters. Try another topic or clear the search.<\/p>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"sample-database\">The sample database used in these questions<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">All query questions use these four small tables. They include a few deliberate traps that interviewers love: an employee with no department (a NULL), a department with no employees, two employees tied on salary, a duplicate customer, and an order from a customer who does not exist. Every time you click Run, the query runs on a fresh copy, so DELETE and UPDATE examples never break the others.<\/p>\n\n\n\n<div class=\"cdai cd-sql-play\">\n<span class=\"cd-tag\">SQL playground<\/span>\n<h4 class=\"cd-h\">Run any query on the sample database<\/h4>\n<div class=\"cd-schema\">\n<div class=\"cd-card\"><b>employees<\/b> <span class=\"cd-small\">(14 rows)<\/span><code>emp_id, name, dept_id, manager_id, salary, hire_date, city<\/code><button type=\"button\" class=\"cd-btn cd-peek\" data-t=\"employees\" style=\"margin-top:8px;font-size:.8rem;padding:5px 10px\">View rows<\/button><\/div>\n<div class=\"cd-card\"><b>departments<\/b> <span class=\"cd-small\">(5 rows)<\/span><code>dept_id, dept_name, location<\/code><button type=\"button\" class=\"cd-btn cd-peek\" data-t=\"departments\" style=\"margin-top:8px;font-size:.8rem;padding:5px 10px\">View rows<\/button><\/div>\n<div class=\"cd-card\"><b>customers<\/b> <span class=\"cd-small\">(8 rows)<\/span><code>customer_id, name, email, city, signup_date<\/code><button type=\"button\" class=\"cd-btn cd-peek\" data-t=\"customers\" style=\"margin-top:8px;font-size:.8rem;padding:5px 10px\">View rows<\/button><\/div>\n<div class=\"cd-card\"><b>orders<\/b> <span class=\"cd-small\">(16 rows)<\/span><code>order_id, customer_id, order_date, amount, status<\/code><button type=\"button\" class=\"cd-btn cd-peek\" data-t=\"orders\" style=\"margin-top:8px;font-size:.8rem;padding:5px 10px\">View rows<\/button><\/div>\n<\/div>\n<label for=\"cd-sql-input\" class=\"cd-small\" style=\"display:block;margin-bottom:6px\">Write your query (Ctrl + Enter to run)<\/label>\n<textarea id=\"cd-sql-input\" spellcheck=\"false\">SELECT d.dept_name, COUNT(*) AS employees, MAX(e.salary) AS top_salary\nFROM employees e\nJOIN departments d ON d.dept_id = e.dept_id\nGROUP BY d.dept_name\nORDER BY top_salary DESC;<\/textarea>\n<div class=\"cd-row\" style=\"margin-top:10px\"><button type=\"button\" class=\"cd-btn cd-primary cd-play-run\">\u25b6 Run query<\/button>\n<button type=\"button\" class=\"cd-btn cd-ex\" data-sql=\"SELECT name, salary, DENSE_RANK() OVER (ORDER BY salary DESC) AS rnk&#10;FROM employees;\">Try: ranking<\/button>\n<button type=\"button\" class=\"cd-btn cd-ex\" data-sql=\"SELECT c.name, SUM(o.amount) AS spent&#10;FROM customers c JOIN orders o ON o.customer_id = c.customer_id&#10;GROUP BY c.customer_id, c.name ORDER BY spent DESC;\">Try: join + group<\/button><\/div>\n<div class=\"cd-play-out\" hidden><\/div>\n<p class=\"cd-small\" style=\"margin:10px 0 0\">The engine is SQLite running in your browser (about 1 MB, loaded the first time you click Run). Syntax that differs in MySQL, PostgreSQL or SQL Server is pointed out in the answers.<\/p>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"how-to-prepare\">How to prepare for a SQL interview<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li><strong>Get the concepts airtight.<\/strong> Keys, joins, NULL behaviour, GROUP BY vs HAVING, normalization, indexes and ACID come up in almost every interview.<\/li>\n\n\n<li><strong>Write queries by hand, then run them.<\/strong> Predict the output first. Most mistakes come from NULLs, duplicates in joins and ties in rankings.<\/li>\n\n\n<li><strong>Master the top patterns:<\/strong> Nth highest salary, duplicates, anti-joins (customers with no orders), top N per group, running totals, month-over-month change, and self joins.<\/li>\n\n\n<li><strong>Learn window functions properly.<\/strong> ROW_NUMBER, RANK, DENSE_RANK, LAG and SUM OVER separate intermediate candidates from beginners, especially for data analyst roles.<\/li>\n\n\n<li><strong>Know your target database.<\/strong> Date functions, LIMIT vs TOP, and string concatenation differ between MySQL, PostgreSQL and SQL Server. The answers below flag these differences.<\/li>\n\n\n<li><strong>Pair SQL with a programming language.<\/strong> Many interviews also test Python. Our <a href=\"https:\/\/codeanddebug.in\/blog\/python-interview-questions\/\">100 Python interview questions<\/a> page uses the same practice format.<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"sql-interview-questions-for-freshers\">SQL interview questions for freshers<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">These 40 basic SQL interview questions cover what campus and entry-level interviews ask most: SQL command types, keys and constraints, NULL handling, filtering, joins, aggregation, normalization, views, transactions, and the classic beginner queries such as the second highest salary, duplicates and customers with no orders.<\/p>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-1\" data-level=\"Freshers\" data-type=\"Concept\" data-topic=\"Basics\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q1<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Basics<\/span><\/div><h3 class=\"cd-q-title\">1. What is SQL?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>SQL (Structured Query Language) is the standard language for storing, reading and changing data in relational databases such as MySQL, PostgreSQL, Oracle, SQL Server and SQLite. You describe <em>what<\/em> data you want, and the database engine works out <em>how<\/em> to fetch it, which is why SQL is called a <strong>declarative<\/strong> language.<\/p>\n<p>With SQL you can create tables, insert, update and delete rows, query and combine data across tables, and control access and transactions. Each database adds its own extensions (MySQL, T-SQL in SQL Server, PL\/SQL in Oracle), but the core syntax is standardised by ANSI\/ISO and works almost everywhere.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT name, salary\nFROM employees\nWHERE salary &gt; 100000\nORDER BY salary DESC;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nname         | salary\n-------------+-------\nRajesh Kumar | 250000\nPriya Sharma | 150000\nKaran Mehta  | 120000\nKavya Reddy  | 120000\nPooja Nair   | 110000\n(5 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-2\" data-level=\"Freshers\" data-type=\"Concept\" data-topic=\"Basics\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q2<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Basics<\/span><\/div><h3 class=\"cd-q-title\">2. What is the difference between a DBMS and an RDBMS?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>A <strong>DBMS<\/strong> (Database Management System) is any software that stores and manages data, which could be files, documents or key-value pairs. An <strong>RDBMS<\/strong> (Relational DBMS) stores data in <strong>tables<\/strong> of rows and columns, links tables through keys, enforces integrity rules, and is queried with SQL.<\/p>\n<table><thead><tr><th><\/th><th>DBMS<\/th><th>RDBMS<\/th><\/tr><\/thead><tbody>\n<tr><td>Data storage<\/td><td>Files, documents, hierarchies<\/td><td>Related tables<\/td><\/tr>\n<tr><td>Relationships<\/td><td>Not enforced<\/td><td>Primary and foreign keys<\/td><\/tr>\n<tr><td>Normalisation<\/td><td>Not required<\/td><td>Supported<\/td><\/tr>\n<tr><td>ACID transactions<\/td><td>Not always<\/td><td>Yes<\/td><\/tr>\n<tr><td>Examples<\/td><td>File systems, early XML stores<\/td><td>MySQL, PostgreSQL, Oracle, SQL Server<\/td><\/tr><\/tbody><\/table><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-3\" data-level=\"Freshers\" data-type=\"Concept\" data-topic=\"Basics\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q3<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Basics<\/span><\/div><h3 class=\"cd-q-title\">3. What are the types of SQL commands (DDL, DML, DQL, DCL, TCL)?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><table><thead><tr><th>Type<\/th><th>Purpose<\/th><th>Commands<\/th><\/tr><\/thead><tbody>\n<tr><td>DDL (Data Definition)<\/td><td>Define or change structure<\/td><td><code>CREATE<\/code>, <code>ALTER<\/code>, <code>DROP<\/code>, <code>TRUNCATE<\/code>, <code>RENAME<\/code><\/td><\/tr>\n<tr><td>DML (Data Manipulation)<\/td><td>Change the data<\/td><td><code>INSERT<\/code>, <code>UPDATE<\/code>, <code>DELETE<\/code>, <code>MERGE<\/code><\/td><\/tr>\n<tr><td>DQL (Data Query)<\/td><td>Read data<\/td><td><code>SELECT<\/code><\/td><\/tr>\n<tr><td>DCL (Data Control)<\/td><td>Permissions<\/td><td><code>GRANT<\/code>, <code>REVOKE<\/code><\/td><\/tr>\n<tr><td>TCL (Transaction Control)<\/td><td>Manage transactions<\/td><td><code>COMMIT<\/code>, <code>ROLLBACK<\/code>, <code>SAVEPOINT<\/code><\/td><\/tr><\/tbody><\/table>\n<p>Some textbooks put <code>SELECT<\/code> under DML. Either answer is accepted if you explain it.<\/p><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-4\" data-level=\"Freshers\" data-type=\"Concept\" data-topic=\"Keys &amp; constraints\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q4<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Keys &amp; constraints<\/span><\/div><h3 class=\"cd-q-title\">4. What is a primary key?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>A primary key is a column, or set of columns, that <strong>uniquely identifies each row<\/strong> in a table. It cannot contain duplicates and cannot be NULL, and a table can have only one primary key. Most databases automatically create an index on it, so lookups by primary key are fast. In our sample database, <code>emp_id<\/code> is the primary key of <code>employees<\/code>, so inserting a second row with an existing id fails:<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>INSERT INTO employees (emp_id, name, salary)\nVALUES (1, &#x27;Duplicate Person&#x27;, 50000);<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nError: UNIQUE constraint failed: employees.emp_id<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-5\" data-level=\"Freshers\" data-type=\"Concept\" data-topic=\"Keys &amp; constraints\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q5<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Keys &amp; constraints<\/span><\/div><h3 class=\"cd-q-title\">5. What is a foreign key?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>A foreign key is a column in one table that refers to the primary key of another table. It enforces <strong>referential integrity<\/strong>: you cannot insert a value that does not exist in the parent table, or delete a parent row that children still point to (unless you specify an action like <code>ON DELETE CASCADE<\/code>). Here <code>employees.dept_id<\/code> references <code>departments.dept_id<\/code>, so department 42 is rejected.<\/p>\n<p>Note: SQLite only enforces foreign keys after <code>PRAGMA foreign_keys = ON<\/code>. MySQL (InnoDB), PostgreSQL and SQL Server enforce them by default.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>PRAGMA foreign_keys = ON;\nINSERT INTO employees (emp_id, name, dept_id, salary)\nVALUES (50, &#x27;New Joiner&#x27;, 42, 60000);<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nError: FOREIGN KEY constraint failed<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-6\" data-level=\"Freshers\" data-type=\"Concept\" data-topic=\"Keys &amp; constraints\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q6<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Keys &amp; constraints<\/span><\/div><h3 class=\"cd-q-title\">6. What is the difference between a primary key and a unique key?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><table><thead><tr><th><\/th><th>Primary key<\/th><th>Unique key<\/th><\/tr><\/thead><tbody>\n<tr><td>Purpose<\/td><td>Identifies each row<\/td><td>Prevents duplicate values in a column<\/td><\/tr>\n<tr><td>NULL allowed?<\/td><td>No<\/td><td>Yes (usually one NULL, or several depending on the database)<\/td><\/tr>\n<tr><td>How many per table<\/td><td>Only one<\/td><td>Many<\/td><\/tr>\n<tr><td>Default index<\/td><td>Clustered in SQL Server and MySQL InnoDB<\/td><td>Non-clustered<\/td><\/tr><\/tbody><\/table>\n<p>Example: <code>emp_id<\/code> is the primary key, while <code>email<\/code> or <code>pan_number<\/code> would be unique keys.<\/p><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-7\" data-level=\"Freshers\" data-type=\"Concept\" data-topic=\"Keys &amp; constraints\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q7<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Keys &amp; constraints<\/span><\/div><h3 class=\"cd-q-title\">7. What are constraints in SQL?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>Constraints are rules on columns that the database enforces automatically, so bad data never gets in:<\/p>\n<ul><li><code>NOT NULL<\/code>: a value is required.<\/li><li><code>UNIQUE<\/code>: no duplicates.<\/li><li><code>PRIMARY KEY<\/code>: <code>NOT NULL<\/code> plus <code>UNIQUE<\/code>, identifies each row.<\/li><li><code>FOREIGN KEY<\/code>: value must exist in the referenced table.<\/li><li><code>CHECK<\/code>: value must satisfy a condition.<\/li><li><code>DEFAULT<\/code>: value used when none is given.<\/li><\/ul><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>CREATE TABLE accounts (\n  id      INTEGER PRIMARY KEY,\n  holder  TEXT NOT NULL,\n  balance INTEGER DEFAULT 0 CHECK (balance &gt;= 0)\n);\nINSERT INTO accounts (id, holder) VALUES (1, &#x27;Riya&#x27;);\nINSERT INTO accounts (id, holder, balance) VALUES (2, &#x27;Kabir&#x27;, -500);<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nError: CHECK constraint failed: balance &gt;= 0<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-8\" data-level=\"Freshers\" data-type=\"Concept\" data-topic=\"Basics\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q8<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Basics<\/span><\/div><h3 class=\"cd-q-title\">8. What is the difference between DELETE, TRUNCATE and DROP?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><table><thead><tr><th><\/th><th>DELETE<\/th><th>TRUNCATE<\/th><th>DROP<\/th><\/tr><\/thead><tbody>\n<tr><td>Type<\/td><td>DML<\/td><td>DDL<\/td><td>DDL<\/td><\/tr>\n<tr><td>What it removes<\/td><td>Rows (all or filtered with WHERE)<\/td><td>All rows<\/td><td>The whole table: data, structure, indexes<\/td><\/tr>\n<tr><td>WHERE clause<\/td><td>Yes<\/td><td>No<\/td><td>No<\/td><\/tr>\n<tr><td>Speed<\/td><td>Slower, logs each row<\/td><td>Very fast, deallocates pages<\/td><td>Fast<\/td><\/tr>\n<tr><td>Triggers fire<\/td><td>Yes<\/td><td>No<\/td><td>No<\/td><\/tr>\n<tr><td>Rollback<\/td><td>Yes, inside a transaction<\/td><td>In PostgreSQL and SQL Server yes; in MySQL and Oracle no (auto-commit)<\/td><td>Same as TRUNCATE<\/td><\/tr>\n<tr><td>Identity \/ auto-increment<\/td><td>Not reset<\/td><td>Reset<\/td><td>Gone with the table<\/td><\/tr><\/tbody><\/table>\n<p>SQLite has no <code>TRUNCATE<\/code>; <code>DELETE FROM table<\/code> without a WHERE clause is optimised to do the same job.<\/p><div class=\"cdai cd-codebox\"><div class=\"cd-codehead\"><span>SQL \u00b7 syntax example<\/span><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><pre><code>DELETE FROM orders WHERE status = &#x27;Cancelled&#x27;;     -- removes 2 rows\nTRUNCATE TABLE orders;                            -- removes all rows (MySQL \/ PostgreSQL)\nDROP TABLE orders;                                -- removes the table itself<\/code><\/pre><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-9\" data-level=\"Freshers\" data-type=\"Query\" data-topic=\"Filtering\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q9<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Filtering<\/span><\/div><h3 class=\"cd-q-title\">9. What is the difference between WHERE and HAVING?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p><code>WHERE<\/code> filters <strong>individual rows before grouping<\/strong>, so it cannot use aggregate functions. <code>HAVING<\/code> filters <strong>groups after<\/strong> <code>GROUP BY<\/code>, so it can use aggregates like <code>COUNT()<\/code> or <code>AVG()<\/code>. You can use both in one query: here WHERE keeps only employees earning above 60,000, then HAVING keeps only departments that still have at least 3 of them.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT dept_id, COUNT(*) AS headcount, AVG(salary) AS avg_salary\nFROM employees\nWHERE salary &gt; 60000\nGROUP BY dept_id\nHAVING COUNT(*) &gt;= 3;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\ndept_id | headcount | avg_salary\n--------+-----------+-----------\n1       | 5         | 142000\n2       | 4         | 81750\n(2 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-10\" data-level=\"Freshers\" data-type=\"Query\" data-topic=\"Filtering\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q10<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Filtering<\/span><\/div><h3 class=\"cd-q-title\">10. What is NULL, and why does = NULL not work?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p><code>NULL<\/code> means &#8220;unknown&#8221; or &#8220;missing&#8221;. It is not zero and not an empty string. Any comparison with NULL, including <code>NULL = NULL<\/code>, gives <strong>UNKNOWN<\/strong>, which WHERE treats as false. That is why <code>WHERE dept_id = NULL<\/code> returns nothing. Always use <code>IS NULL<\/code> or <code>IS NOT NULL<\/code>.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT COUNT(*) AS using_equals FROM employees WHERE dept_id = NULL;\nSELECT name, dept_id FROM employees WHERE dept_id IS NULL;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nusing_equals\n------------\n0\n(1 row)\n\nname          | dept_id\n--------------+--------\nManish Tiwari | NULL\n(1 row)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-11\" data-level=\"Freshers\" data-type=\"Concept\" data-topic=\"Basics\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q11<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Basics<\/span><\/div><h3 class=\"cd-q-title\">11. What is the difference between CHAR and VARCHAR?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p><code>CHAR(n)<\/code> is <strong>fixed length<\/strong>: every value takes exactly n characters, padded with spaces. It suits codes of a fixed size, like country codes (<code>'IN'<\/code>) or PIN codes. <code>VARCHAR(n)<\/code> is <strong>variable length<\/strong>: it stores only the characters you use (up to n) plus a small length prefix, so it saves space for names, emails and addresses.<\/p>\n<p>CHAR can be slightly faster for truly fixed-size data, but VARCHAR is the right default. In Oracle the type is <code>VARCHAR2<\/code>, and PostgreSQL also offers <code>TEXT<\/code> with no length limit.<\/p><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-12\" data-level=\"Freshers\" data-type=\"Concept\" data-topic=\"Joins\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q12<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Joins<\/span><\/div><h3 class=\"cd-q-title\">12. What is a JOIN, and what are the different types?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>A JOIN combines rows from two or more tables based on a related column, usually a foreign key matching a primary key.<\/p>\n<ul><li><strong>INNER JOIN:<\/strong> only rows that match in both tables.<\/li>\n<li><strong>LEFT JOIN:<\/strong> all rows from the left table, plus matches from the right (NULL where none).<\/li>\n<li><strong>RIGHT JOIN:<\/strong> all rows from the right table, plus matches from the left.<\/li>\n<li><strong>FULL OUTER JOIN:<\/strong> all rows from both tables, matched where possible.<\/li>\n<li><strong>CROSS JOIN:<\/strong> every combination of rows (Cartesian product).<\/li>\n<li><strong>SELF JOIN:<\/strong> a table joined to itself, such as employees to their managers.<\/li><\/ul>\n<p>Each one has its own question below with a query you can run.<\/p><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-13\" data-level=\"Freshers\" data-type=\"Query\" data-topic=\"Joins\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q13<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Joins<\/span><\/div><h3 class=\"cd-q-title\">13. Write an INNER JOIN to show each employee with their department name.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>INNER JOIN keeps only rows where the join condition matches in both tables. Manish Tiwari has no department (<code>dept_id<\/code> is NULL), so he disappears from the result, and so does the Marketing department, which has no employees. Table aliases (<code>e<\/code>, <code>d<\/code>) keep the query short.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT e.name, d.dept_name, e.salary\nFROM employees e\nINNER JOIN departments d ON e.dept_id = d.dept_id\nORDER BY d.dept_name, e.salary DESC;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nname         | dept_name   | salary\n-------------+-------------+-------\nRajesh Kumar | Engineering | 250000\nPriya Sharma | Engineering | 150000\nKavya Reddy  | Engineering | 120000\nAmit Verma   | Engineering | 95000\nSneha Iyer   | Engineering | 95000\nPooja Nair   | Finance     | 110000\nArjun Patel  | Finance     | 75000\nAnanya Rao   | HR          | 85000\nVikram Joshi | HR          | 55000\nKaran Mehta  | Sales       | 120000\nDivya Menon  | Sales       | 72000\nNeha Gupta   | Sales       | 70000\nRohit Singh  | Sales       | 65000\n(13 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-14\" data-level=\"Freshers\" data-type=\"Query\" data-topic=\"Joins\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q14<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Joins<\/span><\/div><h3 class=\"cd-q-title\">14. What does a LEFT JOIN return? Show an example.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>LEFT JOIN returns <strong>every row from the left table<\/strong>, and fills the right table&#8217;s columns with NULL when there is no match. Here all 5 departments appear, including Marketing with zero employees. Note that <code>COUNT(e.emp_id)<\/code> counts only non-NULL values, which is why Marketing shows 0 instead of 1.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT d.dept_name, COUNT(e.emp_id) AS employees\nFROM departments d\nLEFT JOIN employees e ON e.dept_id = d.dept_id\nGROUP BY d.dept_name\nORDER BY employees DESC;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\ndept_name   | employees\n------------+----------\nEngineering | 5\nSales       | 4\nHR          | 2\nFinance     | 2\nMarketing   | 0\n(5 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-15\" data-level=\"Freshers\" data-type=\"Concept\" data-topic=\"Database design\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q15<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Database design<\/span><\/div><h3 class=\"cd-q-title\">15. What is normalization? Explain 1NF, 2NF and 3NF.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>Normalization organises tables to <strong>reduce duplicate data and avoid update anomalies<\/strong> (for example, a customer&#8217;s city stored in 50 order rows and updated in only 49).<\/p>\n<ul><li><strong>1NF:<\/strong> each column holds atomic (single) values, there are no repeating groups, and each row is unique. A <code>phone_numbers<\/code> column holding &#8220;98xx, 99xx&#8221; breaks 1NF.<\/li>\n<li><strong>2NF:<\/strong> 1NF plus no <em>partial dependency<\/em>: every non-key column depends on the whole primary key, not just part of a composite key.<\/li>\n<li><strong>3NF:<\/strong> 2NF plus no <em>transitive dependency<\/em>: non-key columns depend only on the key, not on other non-key columns. Storing <code>dept_name<\/code> in <code>employees<\/code> breaks 3NF, because it depends on <code>dept_id<\/code>, so we keep it in a separate <code>departments<\/code> table.<\/li><\/ul>\n<p>BCNF, 4NF and 5NF go further, but 3NF is the usual target for transactional systems.<\/p><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-16\" data-level=\"Freshers\" data-type=\"Concept\" data-topic=\"Database design\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q16<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Database design<\/span><\/div><h3 class=\"cd-q-title\">16. What is denormalization and when would you use it?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>Denormalization deliberately adds redundant data, for example storing <code>dept_name<\/code> directly in a reporting table, to <strong>avoid expensive joins and speed up reads<\/strong>. The cost is extra storage and the risk of inconsistent data, because the same fact lives in several places and must be kept in sync.<\/p>\n<p>It is common in reporting databases, data warehouses (star schemas), caches and read-heavy dashboards, where fast reads matter more than write efficiency. Transactional systems (OLTP) usually stay normalized.<\/p><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-17\" data-level=\"Freshers\" data-type=\"Concept\" data-topic=\"Indexes\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q17<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Indexes<\/span><\/div><h3 class=\"cd-q-title\">17. What is an index, and how does it speed up queries?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>An index is a separate data structure, usually a <strong>B-tree<\/strong>, that keeps a column&#8217;s values sorted with pointers to the matching rows, like the index at the back of a book. Without one, the database scans every row (a full table scan). With one, it can jump to the matching rows in O(log n).<\/p>\n<p>The trade-off: indexes use extra storage and slow down <code>INSERT<\/code>, <code>UPDATE<\/code> and <code>DELETE<\/code>, because every index must be updated too. Index the columns you filter, join and sort on often. <code>EXPLAIN QUERY PLAN<\/code> (SQLite) or <code>EXPLAIN<\/code> (MySQL, PostgreSQL) shows whether an index is used:<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>CREATE INDEX idx_emp_city ON employees(city);\nEXPLAIN QUERY PLAN\nSELECT name FROM employees WHERE city = &#x27;Mumbai&#x27;;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nid | parent | notused | detail\n---+--------+---------+---------------------------------------------------\n3  | 0      | 0       | SEARCH employees USING INDEX idx_emp_city (city=?)\n(1 row)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-18\" data-level=\"Freshers\" data-type=\"Query\" data-topic=\"Views\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q18<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Views<\/span><\/div><h3 class=\"cd-q-title\">18. What is a view?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>A view is a <strong>saved SELECT query that behaves like a virtual table<\/strong>. It stores no data itself (unless it is a materialized view); every time you query it, the underlying query runs. Views are used to simplify complex joins, to give users access to only some columns (hiding salary, for example), and to keep a stable interface while underlying tables change.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>CREATE VIEW employee_directory AS\nSELECT e.name, d.dept_name, e.city\nFROM employees e\nLEFT JOIN departments d ON e.dept_id = d.dept_id;\n\nSELECT * FROM employee_directory WHERE city = &#x27;Mumbai&#x27;;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nname        | dept_name | city\n------------+-----------+-------\nKaran Mehta | Sales     | Mumbai\nNeha Gupta  | Sales     | Mumbai\nPooja Nair  | Finance   | Mumbai\nDivya Menon | Sales     | Mumbai\n(4 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-19\" data-level=\"Freshers\" data-type=\"Query\" data-topic=\"Set operations\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q19<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Set operations<\/span><\/div><h3 class=\"cd-q-title\">19. What is the difference between UNION and UNION ALL?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>Both stack the results of two SELECT queries with the same number of columns and compatible types. <code>UNION<\/code> <strong>removes duplicate rows<\/strong>, which requires a sort or hash step. <code>UNION ALL<\/code> keeps every row, so it is faster. Use UNION ALL unless you actually need de-duplication. Below, UNION returns each city once, while UNION ALL keeps all 8 rows, duplicates included.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT city FROM employees WHERE city IN (&#x27;Mumbai&#x27;, &#x27;Pune&#x27;)\nUNION\nSELECT location FROM departments WHERE location = &#x27;Mumbai&#x27;;\n\nSELECT COUNT(*) AS union_all_rows FROM (\n  SELECT city FROM employees WHERE city IN (&#x27;Mumbai&#x27;, &#x27;Pune&#x27;)\n  UNION ALL\n  SELECT location FROM departments WHERE location = &#x27;Mumbai&#x27;\n);<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\ncity\n------\nMumbai\nPune\n(2 rows)\n\nunion_all_rows\n--------------\n8\n(1 row)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-20\" data-level=\"Freshers\" data-type=\"Query\" data-topic=\"Aggregation\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q20<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Aggregation<\/span><\/div><h3 class=\"cd-q-title\">20. What are aggregate functions?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>Aggregate functions calculate a single value from many rows: <code>COUNT()<\/code>, <code>SUM()<\/code>, <code>AVG()<\/code>, <code>MIN()<\/code> and <code>MAX()<\/code>. They <strong>ignore NULL values<\/strong> (except <code>COUNT(*)<\/code>), and they are usually combined with <code>GROUP BY<\/code> to get one result per group.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT COUNT(*)     AS total_orders,\n       SUM(amount)  AS revenue,\n       AVG(amount)  AS avg_order,\n       MIN(amount)  AS smallest,\n       MAX(amount)  AS largest\nFROM orders\nWHERE status = &#x27;Delivered&#x27;;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\ntotal_orders | revenue | avg_order | smallest | largest\n-------------+---------+-----------+----------+--------\n12           | 33200   | 2766.6667 | 600      | 5600\n(1 row)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-21\" data-level=\"Freshers\" data-type=\"Query\" data-topic=\"Aggregation\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q21<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Aggregation<\/span><\/div><h3 class=\"cd-q-title\">21. How does GROUP BY work?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p><code>GROUP BY<\/code> splits rows into groups that share the same value in the listed columns, and aggregate functions then run once per group. Every column in the SELECT list must either be in the GROUP BY or be inside an aggregate function. MySQL can relax this when <code>ONLY_FULL_GROUP_BY<\/code> is off, but relying on that gives unpredictable results.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT dept_id,\n       COUNT(*)            AS headcount,\n       ROUND(AVG(salary))  AS avg_salary,\n       MAX(salary)         AS max_salary\nFROM employees\nWHERE dept_id IS NOT NULL\nGROUP BY dept_id\nORDER BY avg_salary DESC;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\ndept_id | headcount | avg_salary | max_salary\n--------+-----------+------------+-----------\n1       | 5         | 142000     | 250000\n4       | 2         | 92500      | 110000\n2       | 4         | 81750      | 120000\n3       | 2         | 70000      | 85000\n(4 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-22\" data-level=\"Freshers\" data-type=\"Query\" data-topic=\"Filtering\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q22<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Filtering<\/span><\/div><h3 class=\"cd-q-title\">22. How do you get the top N rows? (LIMIT, TOP, FETCH FIRST)<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>Sort with <code>ORDER BY<\/code>, then limit the rows. The syntax differs by database:<\/p>\n<ul><li>MySQL, PostgreSQL, SQLite: <code>LIMIT 3<\/code> (with <code>OFFSET<\/code> for paging)<\/li>\n<li>SQL Server: <code>SELECT TOP 3 ...<\/code><\/li>\n<li>Oracle 12c+ and standard SQL: <code>FETCH FIRST 3 ROWS ONLY<\/code><\/li><\/ul>\n<p>Without ORDER BY, the database may return any 3 rows. Also note that two employees tie at 120000, so &#8220;top 3&#8221; can be ambiguous; window functions (later questions) handle ties properly.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT name, salary\nFROM employees\nORDER BY salary DESC\nLIMIT 3;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nname         | salary\n-------------+-------\nRajesh Kumar | 250000\nPriya Sharma | 150000\nKaran Mehta  | 120000\n(3 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-23\" data-level=\"Freshers\" data-type=\"Query\" data-topic=\"Filtering\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q23<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Filtering<\/span><\/div><h3 class=\"cd-q-title\">23. What does DISTINCT do?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p><code>DISTINCT<\/code> removes duplicate rows from the result. With several columns, it applies to the <strong>combination<\/strong> of those columns. It is often used with COUNT: <code>COUNT(DISTINCT city)<\/code>. Do not use DISTINCT to hide duplicate rows caused by a wrong join; fix the join instead.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT DISTINCT city FROM employees ORDER BY city;\nSELECT COUNT(DISTINCT city) AS unique_cities FROM employees;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\ncity\n---------\nAhmedabad\nBengaluru\nDelhi\nHyderabad\nLucknow\nMumbai\nPune\n(7 rows)\n\nunique_cities\n-------------\n7\n(1 row)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-24\" data-level=\"Freshers\" data-type=\"Query\" data-topic=\"Filtering\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q24<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Filtering<\/span><\/div><h3 class=\"cd-q-title\">24. How do LIKE and wildcards work?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p><code>LIKE<\/code> matches text patterns: <code>%<\/code> means any number of characters and <code>_<\/code> means exactly one character. <code>'A%'<\/code> is starts with A, <code>'%a'<\/code> is ends with a, and <code>'%an%'<\/code> is contains an.<\/p>\n<p>Case sensitivity varies: MySQL and SQLite (for ASCII letters) are case-insensitive by default, PostgreSQL is case-sensitive and offers <code>ILIKE<\/code>. A pattern starting with <code>%<\/code> cannot use a normal index, so it is slow on large tables.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT name FROM employees WHERE name LIKE &#x27;A%&#x27;;\nSELECT name FROM employees WHERE name LIKE &#x27;_a%&#x27;;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nname\n-----------\nAmit Verma\nAnanya Rao\nArjun Patel\n(3 rows)\n\nname\n-------------\nRajesh Kumar\nKaran Mehta\nKavya Reddy\nManish Tiwari\n(4 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-25\" data-level=\"Freshers\" data-type=\"Query\" data-topic=\"Filtering\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q25<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Filtering<\/span><\/div><h3 class=\"cd-q-title\">25. How are BETWEEN and IN used?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p><code>BETWEEN a AND b<\/code> is <strong>inclusive<\/strong> on both ends and works for numbers, dates and text. <code>IN (...)<\/code> is a cleaner way to write several OR conditions. Both have NOT versions. With dates stored as datetimes, be careful: <code>BETWEEN '2025-01-01' AND '2025-01-31'<\/code> misses times later on 31 January, so prefer <code>&gt;= start AND &lt; next_day<\/code>.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT name, salary FROM employees\nWHERE salary BETWEEN 70000 AND 95000\n  AND city IN (&#x27;Mumbai&#x27;, &#x27;Bengaluru&#x27;, &#x27;Hyderabad&#x27;)\nORDER BY salary;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nname        | salary\n------------+-------\nNeha Gupta  | 70000\nDivya Menon | 72000\nAmit Verma  | 95000\nSneha Iyer  | 95000\n(4 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-26\" data-level=\"Freshers\" data-type=\"Query\" data-topic=\"Basics\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q26<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Basics<\/span><\/div><h3 class=\"cd-q-title\">26. What are aliases in SQL?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>An alias is a temporary name for a column or table within one query, written with <code>AS<\/code> (optional for tables, and not allowed before table aliases in Oracle). Column aliases make output readable; table aliases shorten joins and are <em>required<\/em> for self joins. In standard SQL you cannot use a column alias in WHERE, because WHERE runs before SELECT, but you can use it in ORDER BY.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT e.name AS employee,\n       e.salary * 12 AS annual_ctc\nFROM employees AS e\nORDER BY annual_ctc DESC\nLIMIT 3;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nemployee     | annual_ctc\n-------------+-----------\nRajesh Kumar | 3000000\nPriya Sharma | 1800000\nKaran Mehta  | 1440000\n(3 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-27\" data-level=\"Freshers\" data-type=\"Query\" data-topic=\"Aggregation\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q27<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Aggregation<\/span><\/div><h3 class=\"cd-q-title\">27. What is the difference between COUNT(*), COUNT(column) and COUNT(DISTINCT column)?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><ul><li><code>COUNT(*)<\/code> counts all rows, including those with NULLs.<\/li>\n<li><code>COUNT(column)<\/code> counts rows where that column is <strong>not NULL<\/strong>.<\/li>\n<li><code>COUNT(DISTINCT column)<\/code> counts unique non-NULL values.<\/li><\/ul>\n<p>Manish Tiwari has a NULL <code>dept_id<\/code>, so the counts differ:<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT COUNT(*)                AS all_rows,\n       COUNT(dept_id)          AS with_dept,\n       COUNT(DISTINCT dept_id) AS unique_depts\nFROM employees;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nall_rows | with_dept | unique_depts\n---------+-----------+-------------\n14       | 13        | 4\n(1 row)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-28\" data-level=\"Freshers\" data-type=\"Query\" data-topic=\"Subqueries\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q28<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Subqueries<\/span><\/div><h3 class=\"cd-q-title\">28. What is a subquery? Give an example.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>A subquery is a query nested inside another query. It can appear in WHERE (the most common), in FROM (as a derived table), or in SELECT (as a scalar value). Here the inner query computes the company-wide average salary once, and the outer query keeps employees above it.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT name, salary\nFROM employees\nWHERE salary &gt; (SELECT AVG(salary) FROM employees)\nORDER BY salary DESC;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nname         | salary\n-------------+-------\nRajesh Kumar | 250000\nPriya Sharma | 150000\nKaran Mehta  | 120000\nKavya Reddy  | 120000\nPooja Nair   | 110000\n(5 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-29\" data-level=\"Freshers\" data-type=\"Concept\" data-topic=\"Transactions\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q29<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Transactions<\/span><\/div><h3 class=\"cd-q-title\">29. What is a transaction? Explain ACID properties.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>A transaction is a group of SQL statements that must succeed or fail <strong>as one unit<\/strong>, like debiting one bank account and crediting another. ACID describes the guarantees:<\/p>\n<ul><li><strong>Atomicity:<\/strong> all statements succeed, or none do.<\/li>\n<li><strong>Consistency:<\/strong> the database moves from one valid state to another, with all constraints satisfied.<\/li>\n<li><strong>Isolation:<\/strong> concurrent transactions do not see each other&#8217;s half-finished work (the degree depends on the isolation level).<\/li>\n<li><strong>Durability:<\/strong> once committed, changes survive crashes, because they are written to a log on disk.<\/li><\/ul><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-30\" data-level=\"Freshers\" data-type=\"Query\" data-topic=\"Transactions\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q30<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Transactions<\/span><\/div><h3 class=\"cd-q-title\">30. How do COMMIT, ROLLBACK and SAVEPOINT work?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p><code>BEGIN<\/code> (or <code>START TRANSACTION<\/code> in MySQL) starts a transaction. <code>COMMIT<\/code> makes its changes permanent. <code>ROLLBACK<\/code> undoes everything since BEGIN. <code>SAVEPOINT name<\/code> marks a point you can roll back to without undoing the whole transaction. Below, the salary hike for Neha is undone, so her salary is unchanged.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>BEGIN;\nUPDATE employees SET salary = salary * 2 WHERE emp_id = 6;\nSELECT name, salary FROM employees WHERE emp_id = 6;\nROLLBACK;\nSELECT name, salary FROM employees WHERE emp_id = 6;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nname       | salary\n-----------+-------\nNeha Gupta | 140000\n(1 row)\n\nname       | salary\n-----------+-------\nNeha Gupta | 70000\n(1 row)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-31\" data-level=\"Freshers\" data-type=\"Concept\" data-topic=\"Basics\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q31<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Basics<\/span><\/div><h3 class=\"cd-q-title\">31. What is a schema in SQL?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>A schema is a <strong>named container for database objects<\/strong> such as tables, views, indexes and procedures, and it also describes their structure. Schemas group related objects and control permissions, for example <code>sales.orders<\/code> and <code>hr.employees<\/code> in the same database.<\/p>\n<p>Meaning differs slightly by product: in MySQL, &#8220;schema&#8221; and &#8220;database&#8221; are synonyms; in PostgreSQL and SQL Server a database contains many schemas (<code>public<\/code> and <code>dbo<\/code> are the defaults); in Oracle each user owns a schema.<\/p><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-32\" data-level=\"Freshers\" data-type=\"Concept\" data-topic=\"Database design\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q32<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Database design<\/span><\/div><h3 class=\"cd-q-title\">32. What is the difference between OLTP and OLAP?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><table><thead><tr><th><\/th><th>OLTP<\/th><th>OLAP<\/th><\/tr><\/thead><tbody>\n<tr><td>Purpose<\/td><td>Run day-to-day transactions<\/td><td>Analyse data for decisions<\/td><\/tr>\n<tr><td>Examples<\/td><td>UPI payments, order placement, ticket booking<\/td><td>Sales dashboards, yearly trends<\/td><\/tr>\n<tr><td>Queries<\/td><td>Many short reads and writes<\/td><td>Few complex reads over huge data<\/td><\/tr>\n<tr><td>Design<\/td><td>Normalized (3NF)<\/td><td>Denormalized (star or snowflake schema)<\/td><\/tr>\n<tr><td>Systems<\/td><td>MySQL, PostgreSQL, Oracle<\/td><td>Snowflake, BigQuery, Redshift, Databricks<\/td><\/tr><\/tbody><\/table>\n<p>Data usually flows from OLTP systems into an OLAP warehouse through ETL or ELT pipelines.<\/p><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-33\" data-level=\"Freshers\" data-type=\"Query\" data-topic=\"Functions\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q33<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Functions<\/span><\/div><h3 class=\"cd-q-title\">33. How do you use CASE in SQL?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p><code>CASE<\/code> is SQL&#8217;s if-else. It returns a value based on conditions checked in order, and the first true one wins. Use it to create categories, map codes to labels, and for conditional aggregation (see the pivot question later). Always add an <code>ELSE<\/code>, otherwise unmatched rows get NULL.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT name, salary,\n       CASE\n         WHEN salary &gt;= 150000 THEN &#x27;Senior band&#x27;\n         WHEN salary &gt;= 90000  THEN &#x27;Mid band&#x27;\n         ELSE &#x27;Junior band&#x27;\n       END AS pay_band\nFROM employees\nORDER BY salary DESC\nLIMIT 6;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nname         | salary | pay_band\n-------------+--------+------------\nRajesh Kumar | 250000 | Senior band\nPriya Sharma | 150000 | Senior band\nKaran Mehta  | 120000 | Mid band\nKavya Reddy  | 120000 | Mid band\nPooja Nair   | 110000 | Mid band\nAmit Verma   | 95000  | Mid band\n(6 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-34\" data-level=\"Freshers\" data-type=\"Query\" data-topic=\"Query practice\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q34<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Query practice<\/span><\/div><h3 class=\"cd-q-title\">34. Find the second highest salary.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>The most asked SQL query question. Two common approaches: take the maximum salary below the overall maximum, or use <code>DISTINCT<\/code> with <code>LIMIT 1 OFFSET 1<\/code>. Both handle ties correctly, because two people with the top salary still leave the second <em>distinct<\/em> value. The <code>DENSE_RANK()<\/code> approach for any Nth salary appears in the intermediate section.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT MAX(salary) AS second_highest\nFROM employees\nWHERE salary &lt; (SELECT MAX(salary) FROM employees);\n\nSELECT DISTINCT salary AS second_highest\nFROM employees\nORDER BY salary DESC\nLIMIT 1 OFFSET 1;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nsecond_highest\n--------------\n150000\n(1 row)\n\nsecond_highest\n--------------\n150000\n(1 row)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-35\" data-level=\"Freshers\" data-type=\"Query\" data-topic=\"Query practice\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q35<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Query practice<\/span><\/div><h3 class=\"cd-q-title\">35. Find employees who joined in a particular year.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>Date functions differ between databases, which interviewers like to check:<\/p>\n<ul><li>MySQL: <code>YEAR(hire_date) = 2020<\/code><\/li><li>PostgreSQL \/ standard SQL: <code>EXTRACT(YEAR FROM hire_date) = 2020<\/code><\/li><li>SQL Server: <code>YEAR(hire_date)<\/code> or <code>DATEPART(year, hire_date)<\/code><\/li><li>SQLite: <code>strftime('%Y', hire_date) = '2020'<\/code><\/li><\/ul>\n<p>Wrapping the column in a function prevents index use, so on large tables a range is faster: <code>hire_date &gt;= '2020-01-01' AND hire_date &lt; '2021-01-01'<\/code>.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT name, hire_date\nFROM employees\nWHERE hire_date &gt;= &#x27;2020-01-01&#x27; AND hire_date &lt; &#x27;2021-01-01&#x27;;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nname        | hire_date\n------------+-----------\nSneha Iyer  | 2020-03-22\nArjun Patel | 2020-08-17\n(2 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-36\" data-level=\"Freshers\" data-type=\"Query\" data-topic=\"Query practice\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q36<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Query practice<\/span><\/div><h3 class=\"cd-q-title\">36. Find cities that have more than one employee.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>Group by city, count, and filter the groups with HAVING. This pattern (GROUP BY plus HAVING COUNT) is the basis for many interview questions, such as departments with more than N employees or customers with more than N orders.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT city, COUNT(*) AS employees\nFROM employees\nGROUP BY city\nHAVING COUNT(*) &gt; 1\nORDER BY employees DESC, city;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\ncity      | employees\n----------+----------\nMumbai    | 4\nBengaluru | 3\nHyderabad | 2\nPune      | 2\n(4 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-37\" data-level=\"Freshers\" data-type=\"Query\" data-topic=\"Query practice\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q37<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Query practice<\/span><\/div><h3 class=\"cd-q-title\">37. How do you find duplicate records?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>Group by the columns that define a duplicate and keep groups with more than one row. Here the same customer (same name and email) signed up twice. To see the full duplicate rows, join this result back to the table or use a window function.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT name, email, COUNT(*) AS copies\nFROM customers\nGROUP BY name, email\nHAVING COUNT(*) &gt; 1;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nname       | email          | copies\n-----------+----------------+-------\nAarav Shah | aarav@mail.com | 2\n(1 row)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-38\" data-level=\"Freshers\" data-type=\"Query\" data-topic=\"Query practice\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q38<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Query practice<\/span><\/div><h3 class=\"cd-q-title\">38. Find customers who have never placed an order.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>Classic &#8220;anti-join&#8221;. Three correct ways: <code>LEFT JOIN ... WHERE right.id IS NULL<\/code>, <code>NOT EXISTS<\/code>, or <code>NOT IN<\/code>. Prefer NOT EXISTS or the LEFT JOIN: <code>NOT IN<\/code> returns no rows at all if the subquery contains a NULL (explained in the intermediate section).<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT c.customer_id, c.name\nFROM customers c\nLEFT JOIN orders o ON o.customer_id = c.customer_id\nWHERE o.order_id IS NULL;\n\nSELECT name FROM customers c\nWHERE NOT EXISTS (\n  SELECT 1 FROM orders o WHERE o.customer_id = c.customer_id\n);<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\ncustomer_id | name\n------------+----------\n108         | Tara Bose\n(1 row)\n\nname\n---------\nTara Bose\n(1 row)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-39\" data-level=\"Freshers\" data-type=\"Query\" data-topic=\"Query practice\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q39<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Query practice<\/span><\/div><h3 class=\"cd-q-title\">39. Find the total amount spent by each customer, highest first.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>Join customers to orders, filter only delivered orders, group by customer and sort by the total. Group by the id as well as the name, because two customers can share a name (Aarav Shah appears twice in our data).<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT c.customer_id, c.name,\n       COUNT(o.order_id) AS orders,\n       SUM(o.amount)     AS total_spent\nFROM customers c\nJOIN orders o ON o.customer_id = c.customer_id\nWHERE o.status = &#x27;Delivered&#x27;\nGROUP BY c.customer_id, c.name\nORDER BY total_spent DESC;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\ncustomer_id | name          | orders | total_spent\n------------+---------------+--------+------------\n101         | Aarav Shah    | 4      | 11800\n102         | Isha Kapoor   | 3      | 7200\n104         | Meera Pillai  | 1      | 5600\n106         | Riya Sen      | 1      | 4300\n103         | Yash Malhotra | 1      | 2700\n107         | Aarav Shah    | 1      | 600\n(6 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-40\" data-level=\"Freshers\" data-type=\"Query\" data-topic=\"Query practice\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q40<\/span><span class=\"cd-pill cd-lv-Freshers\">Freshers<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Query practice<\/span><\/div><h3 class=\"cd-q-title\">40. Delete duplicate rows but keep one copy.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>Keep the row with the smallest id in each duplicate group and delete the rest. This version works in SQLite, PostgreSQL and SQL Server. MySQL does not allow selecting from the same table in a DELETE subquery, so there you use a self join: <code>DELETE c1 FROM customers c1 JOIN customers c2 ON c1.email = c2.email AND c1.customer_id &gt; c2.customer_id;<\/code>. A <code>ROW_NUMBER()<\/code> version appears in the experienced section.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>DELETE FROM customers\nWHERE customer_id NOT IN (\n  SELECT MIN(customer_id)\n  FROM customers\n  GROUP BY name, email\n);\nSELECT customer_id, name, email FROM customers ORDER BY customer_id;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\ncustomer_id | name          | email\n------------+---------------+---------------\n101         | Aarav Shah    | aarav@mail.com\n102         | Isha Kapoor   | isha@mail.com\n103         | Yash Malhotra | yash@mail.com\n104         | Meera Pillai  | meera@mail.com\n105         | Dev Choudhary | dev@mail.com\n106         | Riya Sen      | riya@mail.com\n108         | Tara Bose     | NULL\n(7 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"intermediate-sql-interview-questions\">Intermediate SQL interview questions with queries<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">These 35 questions are asked once the basics are clear, typically for candidates with 1 to 3 years of experience and for data analyst roles: every join type, correlated subqueries, CTEs, window functions (ranking, running totals, LAG and LEAD), pivots, triggers, index design and scenario-based queries.<\/p>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-41\" data-level=\"Intermediate\" data-type=\"Query\" data-topic=\"Joins\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q41<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Joins<\/span><\/div><h3 class=\"cd-q-title\">41. How does a RIGHT JOIN differ from a LEFT JOIN?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>A RIGHT JOIN keeps every row from the <strong>right<\/strong> table and fills the left side with NULL when there is no match. <code>A RIGHT JOIN B<\/code> gives the same result as <code>B LEFT JOIN A<\/code>, so most teams simply write LEFT JOINs for readability. RIGHT JOIN is supported in MySQL, PostgreSQL, SQL Server, Oracle, and SQLite 3.39+.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT e.name, d.dept_name\nFROM employees e\nRIGHT JOIN departments d ON e.dept_id = d.dept_id\nWHERE e.emp_id IS NULL;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nname | dept_name\n-----+----------\nNULL | Marketing\n(1 row)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-42\" data-level=\"Intermediate\" data-type=\"Query\" data-topic=\"Joins\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q42<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Joins<\/span><\/div><h3 class=\"cd-q-title\">42. What is a FULL OUTER JOIN?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>A FULL OUTER JOIN returns all rows from both tables: matched rows side by side, plus unmatched rows from either side with NULLs. Below, customers with no orders appear with a NULL order, and order 15 (from customer 999, who does not exist) appears with a NULL customer. That makes FULL JOIN handy for reconciliation, such as comparing two systems&#8217; records.<\/p>\n<p><strong>MySQL has no FULL OUTER JOIN.<\/strong> Emulate it with <code>LEFT JOIN ... UNION ... RIGHT JOIN<\/code>.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT c.name, o.order_id, o.amount\nFROM customers c\nFULL OUTER JOIN orders o ON o.customer_id = c.customer_id\nWHERE c.customer_id IS NULL OR o.order_id IS NULL;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nname      | order_id | amount\n----------+----------+-------\nTara Bose | NULL     | NULL\nNULL      | 15       | 1000\n(2 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-43\" data-level=\"Intermediate\" data-type=\"Query\" data-topic=\"Joins\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q43<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Joins<\/span><\/div><h3 class=\"cd-q-title\">43. What is a SELF JOIN? Show each employee with their manager.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>A self join joins a table to itself, using two different aliases. It is the standard way to work with hierarchical data stored in one table, like employees and managers or categories and parent categories. A LEFT JOIN keeps Rajesh, the CEO, who has no manager.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT e.name AS employee, m.name AS manager\nFROM employees e\nLEFT JOIN employees m ON e.manager_id = m.emp_id\nORDER BY m.name, e.name;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nemployee      | manager\n--------------+-------------\nRajesh Kumar  | NULL\nVikram Joshi  | Ananya Rao\nManish Tiwari | Karan Mehta\nNeha Gupta    | Karan Mehta\nRohit Singh   | Karan Mehta\nDivya Menon   | Neha Gupta\nArjun Patel   | Pooja Nair\nAmit Verma    | Priya Sharma\nKavya Reddy   | Priya Sharma\nSneha Iyer    | Priya Sharma\nAnanya Rao    | Rajesh Kumar\nKaran Mehta   | Rajesh Kumar\nPooja Nair    | Rajesh Kumar\nPriya Sharma  | Rajesh Kumar\n(14 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-44\" data-level=\"Intermediate\" data-type=\"Query\" data-topic=\"Joins\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q44<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Joins<\/span><\/div><h3 class=\"cd-q-title\">44. What is a CROSS JOIN, and when is it useful?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>A CROSS JOIN returns the <strong>Cartesian product<\/strong>: every row of the first table paired with every row of the second, so m \u00d7 n rows. It is rarely what you want by accident (a missing join condition creates one), but it is useful on purpose to generate combinations, such as every department paired with every month for a report that must show zero rows too.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT COUNT(*) AS combinations\nFROM departments\nCROSS JOIN (SELECT &#x27;Q1&#x27; AS quarter UNION ALL SELECT &#x27;Q2&#x27; UNION ALL SELECT &#x27;Q3&#x27; UNION ALL SELECT &#x27;Q4&#x27;);<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\ncombinations\n------------\n20\n(1 row)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-45\" data-level=\"Intermediate\" data-type=\"Query\" data-topic=\"Subqueries\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q45<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Subqueries<\/span><\/div><h3 class=\"cd-q-title\">45. What is a correlated subquery? Find employees earning more than their department&#x27;s average.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>A <strong>non-correlated<\/strong> subquery runs once and does not depend on the outer query. A <strong>correlated<\/strong> subquery refers to a column of the outer query (<code>e.dept_id<\/code> below), so logically it runs once per outer row. It is easy to read but can be slow on large tables; a join to a grouped derived table or a window function usually performs better.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT e.name, e.dept_id, e.salary\nFROM employees e\nWHERE e.salary &gt; (\n  SELECT AVG(salary) FROM employees x WHERE x.dept_id = e.dept_id\n)\nORDER BY e.dept_id;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nname         | dept_id | salary\n-------------+---------+-------\nRajesh Kumar | 1       | 250000\nPriya Sharma | 1       | 150000\nKaran Mehta  | 2       | 120000\nAnanya Rao   | 3       | 85000\nPooja Nair   | 4       | 110000\n(5 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-46\" data-level=\"Intermediate\" data-type=\"Query\" data-topic=\"Subqueries\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q46<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Subqueries<\/span><\/div><h3 class=\"cd-q-title\">46. What is the difference between IN and EXISTS? What is the NOT IN NULL trap?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p><code>IN<\/code> compares a value against a list returned by the subquery. <code>EXISTS<\/code> just checks whether the subquery returns <em>any<\/em> row, and can stop at the first match. Modern optimisers often run them the same way, but EXISTS is usually preferred for correlated checks.<\/p>\n<p>The trap: <code>NOT IN<\/code> returns <strong>no rows at all<\/strong> if the subquery contains a NULL, because <code>x NOT IN (1, NULL)<\/code> evaluates to UNKNOWN. <code>NOT EXISTS<\/code> does not have this problem. Manish&#8217;s NULL dept_id breaks the first query below:<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT COUNT(*) AS not_in_result\nFROM departments\nWHERE dept_id NOT IN (SELECT dept_id FROM employees);\n\nSELECT dept_name AS not_exists_result\nFROM departments d\nWHERE NOT EXISTS (SELECT 1 FROM employees e WHERE e.dept_id = d.dept_id);<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nnot_in_result\n-------------\n0\n(1 row)\n\nnot_exists_result\n-----------------\nMarketing\n(1 row)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-47\" data-level=\"Intermediate\" data-type=\"Query\" data-topic=\"CTEs\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q47<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">CTEs<\/span><\/div><h3 class=\"cd-q-title\">47. What is a CTE (Common Table Expression)?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>A CTE is a named temporary result defined with <code>WITH<\/code> at the start of a query and used like a table in the main query. CTEs make long queries readable by breaking them into steps, can be referenced more than once, and can be <strong>recursive<\/strong> (see the experienced section). They exist only for that one query. Supported by PostgreSQL, SQL Server, Oracle, SQLite and MySQL 8+.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>WITH dept_stats AS (\n  SELECT dept_id, AVG(salary) AS avg_sal\n  FROM employees\n  GROUP BY dept_id\n)\nSELECT d.dept_name, ROUND(s.avg_sal) AS avg_salary\nFROM dept_stats s\nJOIN departments d ON d.dept_id = s.dept_id\nORDER BY avg_salary DESC;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\ndept_name   | avg_salary\n------------+-----------\nEngineering | 142000\nFinance     | 92500\nSales       | 81750\nHR          | 70000\n(4 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-48\" data-level=\"Intermediate\" data-type=\"Query\" data-topic=\"Window functions\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q48<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Window functions<\/span><\/div><h3 class=\"cd-q-title\">48. What are window functions, and how are they different from GROUP BY?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>A window function computes a value across a set of related rows (the &#8220;window&#8221;) <strong>without collapsing them<\/strong> into one row. GROUP BY returns one row per group; a window function keeps every row and adds the calculated value next to it. The <code>OVER()<\/code> clause defines the window: <code>PARTITION BY<\/code> splits it into groups and <code>ORDER BY<\/code> sets the order inside each group. Common ones: ROW_NUMBER, RANK, DENSE_RANK, LAG, LEAD, SUM\/AVG OVER, NTILE.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT name, dept_id, salary,\n       ROUND(AVG(salary) OVER (PARTITION BY dept_id)) AS dept_avg,\n       salary - ROUND(AVG(salary) OVER (PARTITION BY dept_id)) AS diff\nFROM employees\nWHERE dept_id IN (1, 2)\nORDER BY dept_id, salary DESC;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nname         | dept_id | salary | dept_avg | diff\n-------------+---------+--------+----------+-------\nRajesh Kumar | 1       | 250000 | 142000   | 108000\nPriya Sharma | 1       | 150000 | 142000   | 8000\nKavya Reddy  | 1       | 120000 | 142000   | -22000\nAmit Verma   | 1       | 95000  | 142000   | -47000\nSneha Iyer   | 1       | 95000  | 142000   | -47000\nKaran Mehta  | 2       | 120000 | 81750    | 38250\nDivya Menon  | 2       | 72000  | 81750    | -9750\nNeha Gupta   | 2       | 70000  | 81750    | -11750\nRohit Singh  | 2       | 65000  | 81750    | -16750\n(9 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-49\" data-level=\"Intermediate\" data-type=\"Query\" data-topic=\"Window functions\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q49<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Window functions<\/span><\/div><h3 class=\"cd-q-title\">49. What is the difference between ROW_NUMBER, RANK and DENSE_RANK?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>All three number rows in a given order, but treat ties differently:<\/p>\n<ul><li><code>ROW_NUMBER()<\/code>: always unique (1, 2, 3, 4), ties broken arbitrarily.<\/li>\n<li><code>RANK()<\/code>: ties share a rank, then numbers are <strong>skipped<\/strong> (1, 2, 2, 4).<\/li>\n<li><code>DENSE_RANK()<\/code>: ties share a rank with <strong>no gaps<\/strong> (1, 2, 2, 3).<\/li><\/ul>\n<p>Use DENSE_RANK for &#8220;Nth highest salary&#8221; questions and ROW_NUMBER when you need exactly one row per group.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT name, salary,\n       ROW_NUMBER() OVER (ORDER BY salary DESC) AS row_num,\n       RANK()       OVER (ORDER BY salary DESC) AS rnk,\n       DENSE_RANK() OVER (ORDER BY salary DESC) AS dense_rnk\nFROM employees\nORDER BY salary DESC\nLIMIT 8;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nname         | salary | row_num | rnk | dense_rnk\n-------------+--------+---------+-----+----------\nRajesh Kumar | 250000 | 1       | 1   | 1\nPriya Sharma | 150000 | 2       | 2   | 2\nKaran Mehta  | 120000 | 3       | 3   | 3\nKavya Reddy  | 120000 | 4       | 3   | 3\nPooja Nair   | 110000 | 5       | 5   | 4\nAmit Verma   | 95000  | 6       | 6   | 5\nSneha Iyer   | 95000  | 7       | 6   | 5\nAnanya Rao   | 85000  | 8       | 8   | 6\n(8 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-50\" data-level=\"Intermediate\" data-type=\"Query\" data-topic=\"Window functions\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q50<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Window functions<\/span><\/div><h3 class=\"cd-q-title\">50. Find the Nth highest salary (for example, the 3rd highest).<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>Use <code>DENSE_RANK()<\/code> so that ties do not skip a level, then filter on the rank in an outer query (window functions cannot be used directly in WHERE). Change 3 to any N. Our data has two people tied at 120000, and both are returned for the 3rd highest salary.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>WITH ranked AS (\n  SELECT name, salary,\n         DENSE_RANK() OVER (ORDER BY salary DESC) AS rnk\n  FROM employees\n)\nSELECT name, salary FROM ranked WHERE rnk = 3;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nname        | salary\n------------+-------\nKaran Mehta | 120000\nKavya Reddy | 120000\n(2 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-51\" data-level=\"Intermediate\" data-type=\"Query\" data-topic=\"Window functions\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q51<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Window functions<\/span><\/div><h3 class=\"cd-q-title\">51. Find the top 2 earners in each department.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>&#8220;Top N per group&#8221; is one of the most frequent scenario questions. Partition by department, rank inside each partition, then keep ranks up to N. Use <code>ROW_NUMBER<\/code> for exactly N rows per group, or <code>DENSE_RANK<\/code> to include ties (Engineering has a tie at 95000 for 4th place, which would matter for a top 4).<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>WITH ranked AS (\n  SELECT d.dept_name, e.name, e.salary,\n         ROW_NUMBER() OVER (PARTITION BY e.dept_id ORDER BY e.salary DESC) AS rn\n  FROM employees e\n  JOIN departments d ON d.dept_id = e.dept_id\n)\nSELECT dept_name, name, salary\nFROM ranked\nWHERE rn &lt;= 2\nORDER BY dept_name, salary DESC;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\ndept_name   | name         | salary\n------------+--------------+-------\nEngineering | Rajesh Kumar | 250000\nEngineering | Priya Sharma | 150000\nFinance     | Pooja Nair   | 110000\nFinance     | Arjun Patel  | 75000\nHR          | Ananya Rao   | 85000\nHR          | Vikram Joshi | 55000\nSales       | Karan Mehta  | 120000\nSales       | Divya Menon  | 72000\n(8 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-52\" data-level=\"Intermediate\" data-type=\"Query\" data-topic=\"Window functions\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q52<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Window functions<\/span><\/div><h3 class=\"cd-q-title\">52. Calculate a running total of revenue by order date.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p><code>SUM(...) OVER (ORDER BY ...)<\/code> adds each row&#8217;s value to all the previous ones. Adding <code>PARTITION BY customer_id<\/code> would restart the total for each customer. When the window has an ORDER BY, the default frame is &#8220;from the start to the current row&#8221;.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT order_date, amount,\n       SUM(amount) OVER (ORDER BY order_date) AS running_total\nFROM orders\nWHERE status = &#x27;Delivered&#x27;\nORDER BY order_date\nLIMIT 8;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\norder_date | amount | running_total\n-----------+--------+--------------\n2025-01-15 | 2500   | 2500\n2025-02-05 | 1200   | 3700\n2025-02-18 | 3400   | 7100\n2025-03-20 | 5600   | 12700\n2025-03-25 | 2100   | 14800\n2025-04-22 | 1800   | 16600\n2025-05-11 | 4300   | 20900\n2025-05-28 | 2700   | 23600\n(8 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-53\" data-level=\"Intermediate\" data-type=\"Query\" data-topic=\"Window functions\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q53<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Window functions<\/span><\/div><h3 class=\"cd-q-title\">53. How do LAG and LEAD work? Show month-over-month revenue change.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p><code>LAG(col, n)<\/code> reads the value from n rows <strong>before<\/strong> the current row; <code>LEAD(col, n)<\/code> reads from n rows <strong>after<\/strong>. They are ideal for comparing with the previous period, like growth, churn or time between events. The first row has no previous value, so LAG returns NULL there (or a default if you pass a third argument).<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>WITH monthly AS (\n  SELECT strftime(&#x27;%Y-%m&#x27;, order_date) AS month, SUM(amount) AS revenue\n  FROM orders\n  WHERE status = &#x27;Delivered&#x27;\n  GROUP BY month\n)\nSELECT month, revenue,\n       LAG(revenue) OVER (ORDER BY month) AS prev_month,\n       revenue - LAG(revenue) OVER (ORDER BY month) AS change\nFROM monthly;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nmonth   | revenue | prev_month | change\n--------+---------+------------+-------\n2025-01 | 2500    | NULL       | NULL\n2025-02 | 4600    | 2500       | 2100\n2025-03 | 7700    | 4600       | 3100\n2025-04 | 1800    | 7700       | -5900\n2025-05 | 7000    | 1800       | 5200\n2025-06 | 4500    | 7000       | -2500\n2025-07 | 5100    | 4500       | 600\n(7 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-54\" data-level=\"Intermediate\" data-type=\"Query\" data-topic=\"Functions\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q54<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Functions<\/span><\/div><h3 class=\"cd-q-title\">54. What do COALESCE, IFNULL and NULLIF do?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><ul><li><code>COALESCE(a, b, c)<\/code> returns the first non-NULL argument. It is standard SQL and works everywhere.<\/li>\n<li><code>IFNULL(a, b)<\/code> in MySQL and SQLite, <code>ISNULL(a, b)<\/code> in SQL Server and <code>NVL(a, b)<\/code> in Oracle are two-argument versions.<\/li>\n<li><code>NULLIF(a, b)<\/code> returns NULL if a equals b, otherwise a. Its classic use is avoiding division by zero: <code>x \/ NULLIF(y, 0)<\/code>.<\/li><\/ul><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT name, COALESCE(email, &#x27;not given&#x27;) AS email\nFROM customers\nWHERE customer_id IN (106, 108);\n\nSELECT name, COALESCE(dept_id, 0) AS dept, 100 \/ NULLIF(0, 0) AS safe_division\nFROM employees\nWHERE emp_id = 13;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nname      | email\n----------+--------------\nRiya Sen  | riya@mail.com\nTara Bose | not given\n(2 rows)\n\nname          | dept | safe_division\n--------------+------+--------------\nManish Tiwari | 0    | NULL\n(1 row)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-55\" data-level=\"Intermediate\" data-type=\"Query\" data-topic=\"Functions\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q55<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Functions<\/span><\/div><h3 class=\"cd-q-title\">55. Which string functions are commonly asked?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>The common ones: <code>UPPER<\/code>\/<code>LOWER<\/code>, <code>LENGTH<\/code> (<code>LEN<\/code> in SQL Server), <code>SUBSTR<\/code>\/<code>SUBSTRING<\/code>, <code>TRIM<\/code>, <code>REPLACE<\/code>, <code>INSTR<\/code>\/<code>POSITION<\/code>, and concatenation, which differs: <code>||<\/code> in PostgreSQL, Oracle and SQLite, <code>CONCAT()<\/code> in MySQL, <code>+<\/code> or <code>CONCAT()<\/code> in SQL Server. A favourite question: extract the first name from a full name.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT name,\n       UPPER(name) AS upper_name,\n       LENGTH(name) AS len,\n       SUBSTR(name, 1, INSTR(name, &#x27; &#x27;) - 1) AS first_name,\n       city || &#x27; (&#x27; || SUBSTR(city, 1, 3) || &#x27;)&#x27; AS city_code\nFROM employees\nLIMIT 4;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nname         | upper_name   | len | first_name | city_code\n-------------+--------------+-----+------------+----------------\nRajesh Kumar | RAJESH KUMAR | 12  | Rajesh     | Bengaluru (Ben)\nPriya Sharma | PRIYA SHARMA | 12  | Priya      | Bengaluru (Ben)\nAmit Verma   | AMIT VERMA   | 10  | Amit       | Hyderabad (Hyd)\nSneha Iyer   | SNEHA IYER   | 10  | Sneha      | Bengaluru (Ben)\n(4 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-56\" data-level=\"Intermediate\" data-type=\"Query\" data-topic=\"Functions\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q56<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Functions<\/span><\/div><h3 class=\"cd-q-title\">56. Show monthly revenue for 2025. How do date functions differ across databases?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>Grouping by month is an everyday reporting task, but the function changes per database:<\/p>\n<ul><li>MySQL: <code>DATE_FORMAT(order_date, '%Y-%m')<\/code><\/li><li>PostgreSQL: <code>TO_CHAR(order_date, 'YYYY-MM')<\/code> or <code>DATE_TRUNC('month', order_date)<\/code><\/li><li>SQL Server: <code>FORMAT(order_date, 'yyyy-MM')<\/code><\/li><li>SQLite: <code>strftime('%Y-%m', order_date)<\/code><\/li><\/ul><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT strftime(&#x27;%Y-%m&#x27;, order_date) AS month,\n       COUNT(*)    AS orders,\n       SUM(amount) AS revenue\nFROM orders\nWHERE status &lt;&gt; &#x27;Cancelled&#x27;\nGROUP BY month\nORDER BY month;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nmonth   | orders | revenue\n--------+--------+--------\n2025-01 | 1      | 2500\n2025-02 | 2      | 4600\n2025-03 | 2      | 7700\n2025-04 | 2      | 2750\n2025-05 | 2      | 7000\n2025-06 | 2      | 4500\n2025-07 | 3      | 7300\n(7 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-57\" data-level=\"Intermediate\" data-type=\"Query\" data-topic=\"Aggregation\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q57<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Aggregation<\/span><\/div><h3 class=\"cd-q-title\">57. How do you create a pivot table with conditional aggregation?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>Put a CASE expression inside an aggregate to turn row values into columns. This works in every database, unlike the <code>PIVOT<\/code> keyword, which exists only in SQL Server and Oracle. Here each order status becomes its own column.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT strftime(&#x27;%Y-%m&#x27;, order_date) AS month,\n       SUM(CASE WHEN status = &#x27;Delivered&#x27; THEN 1 ELSE 0 END) AS delivered,\n       SUM(CASE WHEN status = &#x27;Cancelled&#x27; THEN 1 ELSE 0 END) AS cancelled,\n       SUM(CASE WHEN status = &#x27;Pending&#x27;   THEN 1 ELSE 0 END) AS pending\nFROM orders\nGROUP BY month\nORDER BY month;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nmonth   | delivered | cancelled | pending\n--------+-----------+-----------+--------\n2025-01 | 1         | 0         | 0\n2025-02 | 2         | 0         | 0\n2025-03 | 2         | 1         | 0\n2025-04 | 1         | 0         | 1\n2025-05 | 2         | 0         | 0\n2025-06 | 2         | 1         | 0\n2025-07 | 2         | 0         | 1\n(7 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-58\" data-level=\"Intermediate\" data-type=\"Query\" data-topic=\"Query practice\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q58<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Query practice<\/span><\/div><h3 class=\"cd-q-title\">58. Find employees who earn more than their managers.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>A classic self-join question, also on LeetCode (181). Join the table to itself on <code>manager_id = emp_id<\/code> so each row has the employee and their manager side by side, then compare the two salaries. In our data, Divya was hired as a senior specialist and earns slightly more than her team lead Neha.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT e.name AS employee, e.salary, m.name AS manager, m.salary AS manager_salary\nFROM employees e\nJOIN employees m ON e.manager_id = m.emp_id\nWHERE e.salary &gt; m.salary;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nemployee    | salary | manager    | manager_salary\n------------+--------+------------+---------------\nDivya Menon | 72000  | Neha Gupta | 70000\n(1 row)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-59\" data-level=\"Intermediate\" data-type=\"Query\" data-topic=\"Query practice\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q59<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Query practice<\/span><\/div><h3 class=\"cd-q-title\">59. Find departments that have no employees.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>An anti-join again: LEFT JOIN and keep rows where the employee side is NULL, or use NOT EXISTS. Remember the NOT IN NULL trap from an earlier question: <code>NOT IN (SELECT dept_id FROM employees)<\/code> returns nothing here because one dept_id is NULL.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT d.dept_id, d.dept_name\nFROM departments d\nLEFT JOIN employees e ON e.dept_id = d.dept_id\nWHERE e.emp_id IS NULL;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\ndept_id | dept_name\n--------+----------\n5       | Marketing\n(1 row)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-60\" data-level=\"Intermediate\" data-type=\"Query\" data-topic=\"Query practice\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q60<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Query practice<\/span><\/div><h3 class=\"cd-q-title\">60. Find the highest-paid employee in each department, with their name.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>A simple <code>GROUP BY dept_id<\/code> with <code>MAX(salary)<\/code> gives the salary but not the name, and adding <code>name<\/code> to the SELECT list is invalid in standard SQL. Two correct ways: join back to the grouped maximum, or rank with a window function. The join version also returns ties.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT d.dept_name, e.name, e.salary\nFROM employees e\nJOIN (SELECT dept_id, MAX(salary) AS max_sal\n      FROM employees GROUP BY dept_id) m\n  ON e.dept_id = m.dept_id AND e.salary = m.max_sal\nJOIN departments d ON d.dept_id = e.dept_id\nORDER BY e.salary DESC;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\ndept_name   | name         | salary\n------------+--------------+-------\nEngineering | Rajesh Kumar | 250000\nSales       | Karan Mehta  | 120000\nFinance     | Pooja Nair   | 110000\nHR          | Ananya Rao   | 85000\n(4 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-61\" data-level=\"Intermediate\" data-type=\"Query\" data-topic=\"Query practice\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q61<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Query practice<\/span><\/div><h3 class=\"cd-q-title\">61. Find customers with more than 2 delivered orders and total spend above 5000.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>Combine WHERE (filter rows), GROUP BY (one row per customer) and HAVING with two aggregate conditions. Scenario questions like this appear constantly in data analyst interviews.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT customer_id, COUNT(*) AS orders, SUM(amount) AS total\nFROM orders\nWHERE status = &#x27;Delivered&#x27;\nGROUP BY customer_id\nHAVING COUNT(*) &gt; 2 AND SUM(amount) &gt; 5000;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\ncustomer_id | orders | total\n------------+--------+------\n101         | 4      | 11800\n102         | 3      | 7200\n(2 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-62\" data-level=\"Intermediate\" data-type=\"Query\" data-topic=\"Window functions\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q62<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Window functions<\/span><\/div><h3 class=\"cd-q-title\">62. Show each department&#x27;s share of the total salary bill as a percentage.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>Compute the department total with GROUP BY, then divide by the grand total, which a window function gives without a second query: <code>SUM(SUM(salary)) OVER ()<\/code> means &#8220;sum the grouped sums across the whole result&#8221;. Multiply by 100.0 rather than 100 to avoid integer division in databases that truncate integers.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT d.dept_name,\n       SUM(e.salary) AS dept_salary,\n       ROUND(100.0 * SUM(e.salary) \/ SUM(SUM(e.salary)) OVER (), 1) AS pct_of_total\nFROM employees e\nJOIN departments d ON d.dept_id = e.dept_id\nGROUP BY d.dept_name\nORDER BY pct_of_total DESC;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\ndept_name   | dept_salary | pct_of_total\n------------+-------------+-------------\nEngineering | 710000      | 52.1\nSales       | 327000      | 24\nFinance     | 185000      | 13.6\nHR          | 140000      | 10.3\n(4 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-63\" data-level=\"Intermediate\" data-type=\"Query\" data-topic=\"Query practice\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q63<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Query practice<\/span><\/div><h3 class=\"cd-q-title\">63. For each customer, find the first and last order date and the days between them.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>MIN and MAX on a date column give the first and last order. Date arithmetic differs by database: <code>DATEDIFF(last, first)<\/code> in MySQL, <code>last - first<\/code> for DATE values in PostgreSQL, <code>DATEDIFF(day, first, last)<\/code> in SQL Server, and <code>julianday(last) - julianday(first)<\/code> in SQLite.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT customer_id,\n       MIN(order_date) AS first_order,\n       MAX(order_date) AS last_order,\n       CAST(julianday(MAX(order_date)) - julianday(MIN(order_date)) AS INTEGER) AS days_between\nFROM orders\nWHERE customer_id IN (101, 102, 103)\nGROUP BY customer_id;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\ncustomer_id | first_order | last_order | days_between\n------------+-------------+------------+-------------\n101         | 2025-01-15  | 2025-07-30 | 196\n102         | 2025-02-05  | 2025-06-19 | 134\n103         | 2025-03-02  | 2025-05-28 | 87\n(3 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-64\" data-level=\"Intermediate\" data-type=\"Concept\" data-topic=\"Stored code\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q64<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Stored code<\/span><\/div><h3 class=\"cd-q-title\">64. What is a stored procedure?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>A stored procedure is a named block of SQL (with variables, conditions and loops) <strong>saved inside the database<\/strong> and run with <code>CALL<\/code> or <code>EXEC<\/code>. Benefits: logic runs close to the data, fewer network round trips, reusable business rules, and permissions can be granted on the procedure instead of the tables. Downsides: harder to version-control and test, and the syntax is vendor-specific (PL\/SQL, T-SQL, PL\/pgSQL). SQLite does not support stored procedures; this MySQL example is not runnable here:<\/p><div class=\"cdai cd-codebox\"><div class=\"cd-codehead\"><span>SQL \u00b7 syntax example<\/span><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><pre><code>DELIMITER \/\/\nCREATE PROCEDURE give_raise(IN p_dept INT, IN p_pct DECIMAL(5,2))\nBEGIN\n  UPDATE employees\n  SET salary = salary * (1 + p_pct \/ 100)\n  WHERE dept_id = p_dept;\nEND \/\/\nDELIMITER ;\n\nCALL give_raise(2, 10);<\/code><\/pre><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-65\" data-level=\"Intermediate\" data-type=\"Concept\" data-topic=\"Stored code\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q65<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Stored code<\/span><\/div><h3 class=\"cd-q-title\">65. What is the difference between a function and a stored procedure?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><table><thead><tr><th><\/th><th>Function<\/th><th>Stored procedure<\/th><\/tr><\/thead><tbody>\n<tr><td>Returns<\/td><td>Must return a value (scalar or table)<\/td><td>May return nothing, output parameters or result sets<\/td><\/tr>\n<tr><td>Use in SELECT<\/td><td>Yes<\/td><td>No, called with CALL or EXEC<\/td><\/tr>\n<tr><td>Change data (INSERT\/UPDATE)<\/td><td>Generally not allowed<\/td><td>Yes<\/td><\/tr>\n<tr><td>Transactions<\/td><td>Cannot manage them<\/td><td>Can COMMIT and ROLLBACK<\/td><\/tr>\n<tr><td>Typical use<\/td><td>Calculations, formatting<\/td><td>Business processes, batch jobs<\/td><\/tr><\/tbody><\/table><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-66\" data-level=\"Intermediate\" data-type=\"Query\" data-topic=\"Stored code\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q66<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Stored code<\/span><\/div><h3 class=\"cd-q-title\">66. What is a trigger? Show an example.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>A trigger is code that runs <strong>automatically<\/strong> when an INSERT, UPDATE or DELETE happens on a table, either BEFORE or AFTER the change. Typical uses: audit logs, enforcing complex rules, and keeping derived columns in sync. Use them sparingly, because hidden logic makes bugs hard to trace. This trigger records every salary change:<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>CREATE TABLE salary_audit (emp_id INT, old_salary INT, new_salary INT);\n\nCREATE TRIGGER trg_salary_change\nAFTER UPDATE OF salary ON employees\nBEGIN\n  INSERT INTO salary_audit VALUES (OLD.emp_id, OLD.salary, NEW.salary);\nEND;\n\nUPDATE employees SET salary = salary + 5000 WHERE dept_id = 3;\nSELECT * FROM salary_audit;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nemp_id | old_salary | new_salary\n-------+------------+-----------\n8      | 85000      | 90000\n9      | 55000      | 60000\n(2 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-67\" data-level=\"Intermediate\" data-type=\"Concept\" data-topic=\"Indexes\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q67<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Indexes<\/span><\/div><h3 class=\"cd-q-title\">67. What is the difference between a clustered and a non-clustered index?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>A <strong>clustered index<\/strong> decides the physical order of rows on disk: the table data <em>is<\/em> the index&#8217;s leaf level. So a table can have only one clustered index, usually on the primary key. Range scans on it are very fast.<\/p>\n<p>A <strong>non-clustered index<\/strong> is a separate structure holding the indexed column values plus a pointer (row locator or primary key) back to the table row. A table can have many of them, and a lookup may need an extra step to fetch the remaining columns, unless the index <em>covers<\/em> the query.<\/p>\n<p>In MySQL InnoDB the primary key is always the clustered index. In PostgreSQL tables are heaps, and <code>CLUSTER<\/code> only reorders them once.<\/p><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-68\" data-level=\"Intermediate\" data-type=\"Query\" data-topic=\"Indexes\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q68<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Indexes<\/span><\/div><h3 class=\"cd-q-title\">68. What is a composite index, and what is the leftmost prefix rule?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>A composite index covers several columns, for example <code>(dept_id, salary)<\/code>. It is sorted by the first column, then by the second within it. So it helps queries that filter on <code>dept_id<\/code>, or on <code>dept_id<\/code> and <code>salary<\/code>, but generally <strong>not<\/strong> queries filtering only on <code>salary<\/code>: that is the leftmost prefix rule. Put the column used most often in equality filters first.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>CREATE INDEX idx_dept_salary ON employees(dept_id, salary);\nEXPLAIN QUERY PLAN SELECT name FROM employees WHERE dept_id = 1 AND salary &gt; 100000;\nEXPLAIN QUERY PLAN SELECT name FROM employees WHERE salary &gt; 100000;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nid | parent | notused | detail\n---+--------+---------+----------------------------------------------------------------------\n3  | 0      | 0       | SEARCH employees USING INDEX idx_dept_salary (dept_id=? AND salary&gt;?)\n(1 row)\n\nid | parent | notused | detail\n---+--------+---------+---------------\n2  | 0      | 0       | SCAN employees\n(1 row)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-69\" data-level=\"Intermediate\" data-type=\"Concept\" data-topic=\"Keys &amp; constraints\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q69<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Keys &amp; constraints<\/span><\/div><h3 class=\"cd-q-title\">69. What are super keys, candidate keys, alternate keys and composite keys?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><ul><li><strong>Super key:<\/strong> any set of columns that uniquely identifies a row, even with extra columns, like <code>(emp_id, name)<\/code>.<\/li>\n<li><strong>Candidate key:<\/strong> a <em>minimal<\/em> super key, with no unnecessary columns. A table may have several, like <code>emp_id<\/code> and <code>email<\/code>.<\/li>\n<li><strong>Primary key:<\/strong> the candidate key you choose as the main identifier.<\/li>\n<li><strong>Alternate key:<\/strong> the candidate keys not chosen as primary, usually enforced with UNIQUE.<\/li>\n<li><strong>Composite key:<\/strong> a key made of two or more columns, like <code>(order_id, product_id)<\/code> in an order_items table.<\/li>\n<li><strong>Surrogate key:<\/strong> an artificial id with no business meaning (auto-increment or UUID), as opposed to a <strong>natural key<\/strong> like a PAN number.<\/li><\/ul><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-70\" data-level=\"Intermediate\" data-type=\"Query\" data-topic=\"Keys &amp; constraints\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q70<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Keys &amp; constraints<\/span><\/div><h3 class=\"cd-q-title\">70. What does ON DELETE CASCADE do?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>It defines what happens to child rows when the parent row is deleted. <code>CASCADE<\/code> deletes the children automatically. The other options are <code>SET NULL<\/code>, <code>SET DEFAULT<\/code>, and <code>RESTRICT<\/code>\/<code>NO ACTION<\/code> (block the delete, the default). <code>ON UPDATE<\/code> works the same way for key changes. Cascades are convenient but dangerous: one delete can silently remove thousands of rows.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>PRAGMA foreign_keys = ON;\nCREATE TABLE teams (id INTEGER PRIMARY KEY, name TEXT);\nCREATE TABLE members (id INTEGER PRIMARY KEY, team_id INT REFERENCES teams(id) ON DELETE CASCADE, name TEXT);\nINSERT INTO teams VALUES (1, &#x27;Backend&#x27;), (2, &#x27;Data&#x27;);\nINSERT INTO members VALUES (1, 1, &#x27;Riya&#x27;), (2, 1, &#x27;Kabir&#x27;), (3, 2, &#x27;Sneha&#x27;);\nDELETE FROM teams WHERE id = 1;\nSELECT * FROM members;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nid | team_id | name\n---+---------+------\n3  | 2       | Sneha\n(1 row)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-71\" data-level=\"Intermediate\" data-type=\"Concept\" data-topic=\"Database design\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q71<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Database design<\/span><\/div><h3 class=\"cd-q-title\">71. What types of relationships exist between tables?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><ul><li><strong>One-to-one:<\/strong> each row in A matches at most one row in B, such as employee and employee_bank_details. Implement with a foreign key that is also UNIQUE.<\/li>\n<li><strong>One-to-many:<\/strong> one department has many employees. The foreign key goes on the &#8220;many&#8221; side (<code>employees.dept_id<\/code>).<\/li>\n<li><strong>Many-to-many:<\/strong> students and courses. This needs a <strong>junction (bridge) table<\/strong>, like <code>enrollments(student_id, course_id)<\/code>, with a composite primary key and two foreign keys.<\/li><\/ul><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-72\" data-level=\"Intermediate\" data-type=\"Query\" data-topic=\"Set operations\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q72<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Set operations<\/span><\/div><h3 class=\"cd-q-title\">72. What do INTERSECT and EXCEPT (MINUS) do?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p><code>INTERSECT<\/code> returns rows present in both queries. <code>EXCEPT<\/code> returns rows in the first query that are not in the second; Oracle calls it <code>MINUS<\/code>. Both remove duplicates. MySQL added them only in 8.0.31, so older MySQL needs joins or EXISTS instead.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT city FROM employees\nINTERSECT\nSELECT location FROM departments;\n\nSELECT city FROM employees\nEXCEPT\nSELECT location FROM departments;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\ncity\n---------\nBengaluru\nDelhi\nMumbai\nPune\n(4 rows)\n\ncity\n---------\nAhmedabad\nHyderabad\nLucknow\n(3 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-73\" data-level=\"Intermediate\" data-type=\"Concept\" data-topic=\"Basics\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q73<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Basics<\/span><\/div><h3 class=\"cd-q-title\">73. What is the logical order of execution of a SQL query?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>SQL is written in one order but logically processed in another, which explains many errors:<\/p>\n<ol><li><code>FROM<\/code> and <code>JOIN<\/code>: build the combined rows<\/li><li><code>WHERE<\/code>: filter rows<\/li><li><code>GROUP BY<\/code>: form groups<\/li><li><code>HAVING<\/code>: filter groups<\/li><li><code>SELECT<\/code>: compute columns and aliases (window functions run here)<\/li><li><code>DISTINCT<\/code>: remove duplicates<\/li><li><code>ORDER BY<\/code>: sort<\/li><li><code>LIMIT<\/code> \/ <code>OFFSET<\/code> \/ <code>TOP<\/code>: cut rows<\/li><\/ol>\n<p>That is why a SELECT alias cannot be used in WHERE in standard SQL, why aggregates cannot appear in WHERE, and why window functions need a subquery or CTE to be filtered. The optimiser may physically execute steps differently, but results always match this logical order.<\/p><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-74\" data-level=\"Intermediate\" data-type=\"Concept\" data-topic=\"Joins\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q74<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Joins<\/span><\/div><h3 class=\"cd-q-title\">74. What is the difference between JOIN and UNION?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>A <strong>JOIN<\/strong> combines tables <strong>horizontally<\/strong>: it adds columns from another table to each row, matched on a condition. A <strong>UNION<\/strong> combines query results <strong>vertically<\/strong>: it stacks rows from two queries that have the same number of columns with compatible types. Use a JOIN to see employees with their department names; use a UNION to merge last year&#8217;s and this year&#8217;s order tables into one list.<\/p><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-75\" data-level=\"Intermediate\" data-type=\"Query\" data-topic=\"Window functions\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q75<\/span><span class=\"cd-pill cd-lv-Intermediate\">Intermediate<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Window functions<\/span><\/div><h3 class=\"cd-q-title\">75. How do you find the median salary?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>PostgreSQL and Oracle have <code>PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY salary)<\/code>, but MySQL and SQLite do not, so interviewers ask for a portable version: number the rows in both directions, then average the middle one or two. With 14 employees, the median is the average of the 7th and 8th salaries.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>WITH ordered AS (\n  SELECT salary,\n         ROW_NUMBER() OVER (ORDER BY salary) AS rn,\n         COUNT(*) OVER () AS total\n  FROM employees\n)\nSELECT AVG(salary) AS median_salary\nFROM ordered\nWHERE rn IN ((total + 1) \/ 2, (total + 2) \/ 2);<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nmedian_salary\n-------------\n90000\n(1 row)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"sql-interview-questions-for-experienced\">Advanced SQL interview questions for experienced professionals<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">These 25 questions are aimed at candidates with 3 or more years of experience and data engineering roles: isolation levels, deadlocks, query optimization and execution plans, recursive CTEs, gaps and islands, window frames, cohort-style queries, warehouse design, partitioning, MVCC and SQL injection.<\/p>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-76\" data-level=\"Experienced\" data-type=\"Concept\" data-topic=\"Transactions\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q76<\/span><span class=\"cd-pill cd-lv-Experienced\">Experienced<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Transactions<\/span><\/div><h3 class=\"cd-q-title\">76. What are transaction isolation levels and the read phenomena they prevent?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>Isolation levels trade consistency for concurrency. The SQL standard defines four, by which anomalies they allow:<\/p>\n<table><thead><tr><th>Level<\/th><th>Dirty read<\/th><th>Non-repeatable read<\/th><th>Phantom read<\/th><\/tr><\/thead><tbody>\n<tr><td>READ UNCOMMITTED<\/td><td>Possible<\/td><td>Possible<\/td><td>Possible<\/td><\/tr>\n<tr><td>READ COMMITTED<\/td><td>Prevented<\/td><td>Possible<\/td><td>Possible<\/td><\/tr>\n<tr><td>REPEATABLE READ<\/td><td>Prevented<\/td><td>Prevented<\/td><td>Possible (prevented in practice by MySQL InnoDB and PostgreSQL)<\/td><\/tr>\n<tr><td>SERIALIZABLE<\/td><td>Prevented<\/td><td>Prevented<\/td><td>Prevented<\/td><\/tr><\/tbody><\/table>\n<ul><li><strong>Dirty read:<\/strong> reading another transaction&#8217;s uncommitted change, which may be rolled back.<\/li>\n<li><strong>Non-repeatable read:<\/strong> reading the same row twice and getting different values because someone committed an update in between.<\/li>\n<li><strong>Phantom read:<\/strong> running the same range query twice and getting new rows that someone inserted in between.<\/li><\/ul>\n<p>Defaults: READ COMMITTED in PostgreSQL, SQL Server and Oracle; REPEATABLE READ in MySQL InnoDB.<\/p><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-77\" data-level=\"Experienced\" data-type=\"Concept\" data-topic=\"Transactions\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q77<\/span><span class=\"cd-pill cd-lv-Experienced\">Experienced<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Transactions<\/span><\/div><h3 class=\"cd-q-title\">77. What is a deadlock, and how do you prevent one?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>A deadlock happens when two transactions each hold a lock the other needs: T1 locks row A and waits for row B, while T2 locks row B and waits for row A. Neither can continue. The database detects the cycle and kills one transaction (the &#8220;victim&#8221;), which then gets an error and must retry.<\/p>\n<p>Prevention: always access tables and rows in the <strong>same order<\/strong> across the application, keep transactions short, avoid user interaction inside a transaction, use proper indexes so fewer rows get locked, use <code>SELECT ... FOR UPDATE<\/code> deliberately, and add retry logic for deadlock errors.<\/p><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-78\" data-level=\"Experienced\" data-type=\"Concept\" data-topic=\"Performance\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q78<\/span><span class=\"cd-pill cd-lv-Experienced\">Experienced<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Performance<\/span><\/div><h3 class=\"cd-q-title\">78. How do you optimize a slow SQL query?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><ol><li><strong>Read the execution plan<\/strong> (<code>EXPLAIN<\/code> \/ <code>EXPLAIN ANALYZE<\/code>) to find full table scans, bad join orders and large sorts.<\/li>\n<li><strong>Add or fix indexes<\/strong> on columns used in WHERE, JOIN and ORDER BY. Consider composite and covering indexes.<\/li>\n<li><strong>Make filters sargable:<\/strong> avoid functions on indexed columns (<code>WHERE YEAR(d) = 2025<\/code> \u2192 <code>WHERE d &gt;= '2025-01-01' AND d &lt; '2026-01-01'<\/code>) and leading wildcards (<code>LIKE '%x'<\/code>).<\/li>\n<li><strong>Select only the columns you need<\/strong>, not <code>SELECT *<\/code>.<\/li>\n<li><strong>Filter early<\/strong>, and avoid unnecessary DISTINCT, ORDER BY and subqueries that repeat work.<\/li>\n<li><strong>Rewrite correlated subqueries<\/strong> as joins or window functions.<\/li>\n<li><strong>Paginate with keyset pagination<\/strong> (<code>WHERE id &gt; last_id<\/code>) instead of large OFFSETs.<\/li>\n<li><strong>Keep statistics fresh<\/strong> (<code>ANALYZE<\/code>), and for very large tables use partitioning, materialized views or caching.<\/li><\/ol><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-79\" data-level=\"Experienced\" data-type=\"Query\" data-topic=\"Performance\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q79<\/span><span class=\"cd-pill cd-lv-Experienced\">Experienced<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Performance<\/span><\/div><h3 class=\"cd-q-title\">79. How do you read an execution plan? Show the effect of an index.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>The execution plan shows how the database will run a query: which tables it scans, which indexes it uses, the join algorithms (nested loop, hash, merge) and estimated costs. The key thing to spot is a full <strong>SCAN<\/strong> of a large table where you expected an index <strong>SEARCH<\/strong>. Here the same query goes from a full scan to an index search after the index is created. In PostgreSQL use <code>EXPLAIN ANALYZE<\/code> to see actual timings and row counts.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>EXPLAIN QUERY PLAN SELECT * FROM orders WHERE customer_id = 101;\nCREATE INDEX idx_orders_customer ON orders(customer_id);\nEXPLAIN QUERY PLAN SELECT * FROM orders WHERE customer_id = 101;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nid | parent | notused | detail\n---+--------+---------+------------\n2  | 0      | 0       | SCAN orders\n(1 row)\n\nid | parent | notused | detail\n---+--------+---------+--------------------------------------------------------------\n3  | 0      | 0       | SEARCH orders USING INDEX idx_orders_customer (customer_id=?)\n(1 row)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-80\" data-level=\"Experienced\" data-type=\"Concept\" data-topic=\"Indexes\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q80<\/span><span class=\"cd-pill cd-lv-Experienced\">Experienced<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Indexes<\/span><\/div><h3 class=\"cd-q-title\">80. When can an index hurt performance? What is a covering index?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>Indexes are not free:<\/p>\n<ul><li>Every INSERT, UPDATE and DELETE must also update every index, so write-heavy tables slow down.<\/li>\n<li>They use disk and memory.<\/li>\n<li>On <strong>low-selectivity<\/strong> columns (like gender or a boolean), the optimiser often ignores them, because reading most of the table directly is cheaper.<\/li>\n<li>Duplicate or unused indexes add cost with no benefit.<\/li><\/ul>\n<p>A <strong>covering index<\/strong> contains every column a query needs, so the database answers from the index alone without touching the table (an &#8220;index-only scan&#8221;). For example, <code>CREATE INDEX idx ON orders(customer_id, order_date, amount)<\/code> covers <code>SELECT order_date, amount FROM orders WHERE customer_id = 101<\/code>. SQL Server and PostgreSQL also support <code>INCLUDE<\/code> columns for this.<\/p><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-81\" data-level=\"Experienced\" data-type=\"Query\" data-topic=\"CTEs\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q81<\/span><span class=\"cd-pill cd-lv-Experienced\">Experienced<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">CTEs<\/span><\/div><h3 class=\"cd-q-title\">81. Use a recursive CTE to show the full reporting hierarchy.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>A recursive CTE has an <strong>anchor<\/strong> part (the starting rows, here the CEO) and a <strong>recursive<\/strong> part that joins back to the CTE itself to find the next level, repeating until no new rows appear. It is the standard way to walk org charts, category trees, bill-of-materials and graph paths. Use <code>WITH RECURSIVE<\/code> in PostgreSQL, MySQL and SQLite; SQL Server and Oracle accept plain <code>WITH<\/code>.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>WITH RECURSIVE org AS (\n  SELECT emp_id, name, manager_id, 1 AS level, name AS path\n  FROM employees WHERE manager_id IS NULL\n  UNION ALL\n  SELECT e.emp_id, e.name, e.manager_id, o.level + 1, o.path || &#x27; &gt; &#x27; || e.name\n  FROM employees e\n  JOIN org o ON e.manager_id = o.emp_id\n)\nSELECT level, name, path FROM org\nWHERE level &lt;= 3 AND emp_id IN (1, 2, 4, 5, 6, 14)\nORDER BY path;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nlevel | name         | path\n------+--------------+-----------------------------------------\n1     | Rajesh Kumar | Rajesh Kumar\n2     | Karan Mehta  | Rajesh Kumar &gt; Karan Mehta\n3     | Neha Gupta   | Rajesh Kumar &gt; Karan Mehta &gt; Neha Gupta\n2     | Priya Sharma | Rajesh Kumar &gt; Priya Sharma\n3     | Sneha Iyer   | Rajesh Kumar &gt; Priya Sharma &gt; Sneha Iyer\n(5 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-82\" data-level=\"Experienced\" data-type=\"Query\" data-topic=\"CTEs\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q82<\/span><span class=\"cd-pill cd-lv-Experienced\">Experienced<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">CTEs<\/span><\/div><h3 class=\"cd-q-title\">82. Generate a calendar of months and show revenue including months with zero sales.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>Reports often need a row for every period, even ones with no data, and GROUP BY alone skips empty months. Generate the full series with a recursive CTE (PostgreSQL also has <code>generate_series<\/code>), then LEFT JOIN the data and COALESCE missing values to 0. Our data has no delivered orders outside January to July 2025, so August and September show 0.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>WITH RECURSIVE months(m) AS (\n  SELECT &#x27;2025-01-01&#x27;\n  UNION ALL\n  SELECT date(m, &#x27;+1 month&#x27;) FROM months WHERE m &lt; &#x27;2025-09-01&#x27;\n)\nSELECT strftime(&#x27;%Y-%m&#x27;, m) AS month,\n       COALESCE(SUM(o.amount), 0) AS revenue\nFROM months\nLEFT JOIN orders o\n  ON strftime(&#x27;%Y-%m&#x27;, o.order_date) = strftime(&#x27;%Y-%m&#x27;, m)\n AND o.status = &#x27;Delivered&#x27;\nGROUP BY month\nORDER BY month;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nmonth   | revenue\n--------+--------\n2025-01 | 2500\n2025-02 | 4600\n2025-03 | 7700\n2025-04 | 1800\n2025-05 | 7000\n2025-06 | 4500\n2025-07 | 5100\n2025-08 | 0\n2025-09 | 0\n(9 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-83\" data-level=\"Experienced\" data-type=\"Query\" data-topic=\"Window functions\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q83<\/span><span class=\"cd-pill cd-lv-Experienced\">Experienced<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Window functions<\/span><\/div><h3 class=\"cd-q-title\">83. Gaps and islands: find streaks of consecutive login days.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>A famous advanced pattern. For consecutive dates, <code>date \u2212 ROW_NUMBER()<\/code> stays constant within a streak, so it works as a group key for each &#8220;island&#8221;. Then group by it to get each streak&#8217;s start, end and length. The same idea finds consecutive seat numbers, uninterrupted subscriptions or missing invoice numbers (the &#8220;gaps&#8221;).<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>WITH logins(user_id, day) AS (\n  VALUES (1,&#x27;2025-08-01&#x27;),(1,&#x27;2025-08-02&#x27;),(1,&#x27;2025-08-03&#x27;),\n         (1,&#x27;2025-08-06&#x27;),(1,&#x27;2025-08-07&#x27;),(1,&#x27;2025-08-10&#x27;)\n),\ngrp AS (\n  SELECT day,\n         julianday(day) - ROW_NUMBER() OVER (ORDER BY day) AS island\n  FROM logins\n)\nSELECT MIN(day) AS streak_start, MAX(day) AS streak_end, COUNT(*) AS days\nFROM grp\nGROUP BY island\nORDER BY streak_start;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nstreak_start | streak_end | days\n-------------+------------+-----\n2025-08-01   | 2025-08-03 | 3\n2025-08-06   | 2025-08-07 | 2\n2025-08-10   | 2025-08-10 | 1\n(3 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-84\" data-level=\"Experienced\" data-type=\"Query\" data-topic=\"Window functions\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q84<\/span><span class=\"cd-pill cd-lv-Experienced\">Experienced<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Window functions<\/span><\/div><h3 class=\"cd-q-title\">84. Calculate a 3-order moving average using a window frame.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>The frame clause controls exactly which rows the window covers relative to the current row. <code>ROWS BETWEEN 2 PRECEDING AND CURRENT ROW<\/code> averages the current order and the two before it. <code>ROWS<\/code> counts physical rows; <code>RANGE<\/code> groups rows with equal ORDER BY values together, which matters when there are ties. Moving averages smooth noisy metrics like daily sales.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT order_id, order_date, amount,\n       ROUND(AVG(amount) OVER (\n         ORDER BY order_date\n         ROWS BETWEEN 2 PRECEDING AND CURRENT ROW), 0) AS moving_avg_3\nFROM orders\nWHERE status = &#x27;Delivered&#x27;\nORDER BY order_date\nLIMIT 7;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\norder_id | order_date | amount | moving_avg_3\n---------+------------+--------+-------------\n1        | 2025-01-15 | 2500   | 2500\n2        | 2025-02-05 | 1200   | 1850\n3        | 2025-02-18 | 3400   | 2367\n5        | 2025-03-20 | 5600   | 3400\n6        | 2025-03-25 | 2100   | 3700\n8        | 2025-04-22 | 1800   | 3167\n9        | 2025-05-11 | 4300   | 2733\n(7 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-85\" data-level=\"Experienced\" data-type=\"Query\" data-topic=\"Window functions\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q85<\/span><span class=\"cd-pill cd-lv-Experienced\">Experienced<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Window functions<\/span><\/div><h3 class=\"cd-q-title\">85. Find each customer&#x27;s first order.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>&#8220;First, latest, or Nth event per entity&#8221; is a top-N-per-group problem. Number the orders within each customer by date with <code>ROW_NUMBER()<\/code>, then keep row 1. Change the ORDER BY to <code>DESC<\/code> for the latest order. PostgreSQL also offers the shortcut <code>SELECT DISTINCT ON (customer_id) ... ORDER BY customer_id, order_date<\/code>.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>WITH ranked AS (\n  SELECT customer_id, order_id, order_date, amount,\n         ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY order_date) AS rn\n  FROM orders\n)\nSELECT customer_id, order_id, order_date, amount\nFROM ranked\nWHERE rn = 1\nORDER BY customer_id;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\ncustomer_id | order_id | order_date | amount\n------------+----------+------------+-------\n101         | 1        | 2025-01-15 | 2500\n102         | 2        | 2025-02-05 | 1200\n103         | 4        | 2025-03-02 | 800\n104         | 5        | 2025-03-20 | 5600\n105         | 7        | 2025-04-10 | 950\n106         | 9        | 2025-05-11 | 4300\n107         | 13       | 2025-06-25 | 600\n999         | 15       | 2025-07-12 | 1000\n(8 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-86\" data-level=\"Experienced\" data-type=\"Query\" data-topic=\"Window functions\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q86<\/span><span class=\"cd-pill cd-lv-Experienced\">Experienced<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Window functions<\/span><\/div><h3 class=\"cd-q-title\">86. Find customers who ordered in two consecutive months.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>Get each customer&#8217;s distinct order months, then use LAG to compare each month with the previous one. A difference of exactly one month means consecutive activity. This is the building block of retention and cohort analysis. Converting months to a number (year \u00d7 12 + month) makes the difference easy to compute in any database.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>WITH months AS (\n  SELECT DISTINCT customer_id,\n         CAST(strftime(&#x27;%Y&#x27;, order_date) AS INT) * 12 + CAST(strftime(&#x27;%m&#x27;, order_date) AS INT) AS month_no\n  FROM orders\n),\ndiffs AS (\n  SELECT customer_id, month_no,\n         month_no - LAG(month_no) OVER (PARTITION BY customer_id ORDER BY month_no) AS gap\n  FROM months\n)\nSELECT DISTINCT customer_id FROM diffs WHERE gap = 1 ORDER BY customer_id;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\ncustomer_id\n-----------\n101\n102\n(2 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-87\" data-level=\"Experienced\" data-type=\"Query\" data-topic=\"Window functions\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q87<\/span><span class=\"cd-pill cd-lv-Experienced\">Experienced<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Window functions<\/span><\/div><h3 class=\"cd-q-title\">87. Calculate month-over-month revenue growth as a percentage.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>Aggregate to monthly revenue first, then use LAG to bring the previous month&#8217;s value onto the same row. Growth = (current \u2212 previous) \/ previous \u00d7 100. Use <code>NULLIF(previous, 0)<\/code> to avoid dividing by zero, and multiply by 100.0 to force decimal division.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>WITH monthly AS (\n  SELECT strftime(&#x27;%Y-%m&#x27;, order_date) AS month, SUM(amount) AS revenue\n  FROM orders WHERE status = &#x27;Delivered&#x27;\n  GROUP BY month\n)\nSELECT month, revenue,\n       ROUND(100.0 * (revenue - LAG(revenue) OVER (ORDER BY month))\n             \/ NULLIF(LAG(revenue) OVER (ORDER BY month), 0), 1) AS growth_pct\nFROM monthly;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nmonth   | revenue | growth_pct\n--------+---------+-----------\n2025-01 | 2500    | NULL\n2025-02 | 4600    | 84\n2025-03 | 7700    | 67.4\n2025-04 | 1800    | -76.6\n2025-05 | 7000    | 288.9\n2025-06 | 4500    | -35.7\n2025-07 | 5100    | 13.3\n(7 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-88\" data-level=\"Experienced\" data-type=\"Query\" data-topic=\"Window functions\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q88<\/span><span class=\"cd-pill cd-lv-Experienced\">Experienced<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Window functions<\/span><\/div><h3 class=\"cd-q-title\">88. Show a running total of spend that restarts for each customer.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>Add <code>PARTITION BY<\/code> to the running-total window, and the sum restarts for every customer. This answers questions like &#8220;when did each customer cross \u20b95,000 lifetime spend?&#8221;: filter the running total in an outer query.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT customer_id, order_date, amount,\n       SUM(amount) OVER (PARTITION BY customer_id ORDER BY order_date) AS lifetime_spend\nFROM orders\nWHERE status = &#x27;Delivered&#x27; AND customer_id IN (101, 102)\nORDER BY customer_id, order_date;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\ncustomer_id | order_date | amount | lifetime_spend\n------------+------------+--------+---------------\n101         | 2025-01-15 | 2500   | 2500\n101         | 2025-02-18 | 3400   | 5900\n101         | 2025-04-22 | 1800   | 7700\n101         | 2025-07-30 | 4100   | 11800\n102         | 2025-02-05 | 1200   | 1200\n102         | 2025-03-25 | 2100   | 3300\n102         | 2025-06-19 | 3900   | 7200\n(7 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-89\" data-level=\"Experienced\" data-type=\"Query\" data-topic=\"Query practice\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q89<\/span><span class=\"cd-pill cd-lv-Experienced\">Experienced<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Query practice<\/span><\/div><h3 class=\"cd-q-title\">89. Delete duplicates using ROW_NUMBER().<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>Number the rows within each duplicate group, then delete every row with a number above 1. This version is flexible, because the ORDER BY decides which copy survives (here, the earliest signup). SQL Server can delete straight from the CTE (<code>DELETE FROM cte WHERE rn &gt; 1<\/code>); PostgreSQL, MySQL and SQLite need the ids as below.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>WITH ranked AS (\n  SELECT customer_id,\n         ROW_NUMBER() OVER (PARTITION BY email ORDER BY signup_date) AS rn\n  FROM customers\n  WHERE email IS NOT NULL\n)\nDELETE FROM customers\nWHERE customer_id IN (SELECT customer_id FROM ranked WHERE rn &gt; 1);\n\nSELECT COUNT(*) AS customers_left FROM customers;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\ncustomers_left\n--------------\n7\n(1 row)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-90\" data-level=\"Experienced\" data-type=\"Query\" data-topic=\"Query practice\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q90<\/span><span class=\"cd-pill cd-lv-Experienced\">Experienced<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Query practice<\/span><\/div><h3 class=\"cd-q-title\">90. Swap two values in a column with a single UPDATE.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>A tricky classic (LeetCode 627 swaps &#8216;m&#8217; and &#8216;f&#8217;). A single UPDATE with CASE does it in one pass, with no temporary value needed, because each row is evaluated against its original value. Here every Pending order becomes Delivered and every Delivered order becomes Pending.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>UPDATE orders\nSET status = CASE status\n               WHEN &#x27;Pending&#x27;   THEN &#x27;Delivered&#x27;\n               WHEN &#x27;Delivered&#x27; THEN &#x27;Pending&#x27;\n               ELSE status\n             END;\nSELECT status, COUNT(*) AS orders FROM orders GROUP BY status ORDER BY status;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nstatus    | orders\n----------+-------\nCancelled | 2\nDelivered | 2\nPending   | 12\n(3 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-91\" data-level=\"Experienced\" data-type=\"Query\" data-topic=\"Query practice\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q91<\/span><span class=\"cd-pill cd-lv-Experienced\">Experienced<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Query practice<\/span><\/div><h3 class=\"cd-q-title\">91. Find the Nth highest salary without LIMIT, TOP or window functions.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>Interviewers sometimes ban LIMIT and window functions to test logic. A correlated subquery counts how many distinct salaries are higher than each salary. The Nth highest has exactly N \u2212 1 distinct salaries above it. For N = 3:<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>SELECT DISTINCT salary\nFROM employees e1\nWHERE 2 = (\n  SELECT COUNT(DISTINCT e2.salary)\n  FROM employees e2\n  WHERE e2.salary &gt; e1.salary\n);<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\nsalary\n------\n120000\n(1 row)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-92\" data-level=\"Experienced\" data-type=\"Concept\" data-topic=\"Database design\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q92<\/span><span class=\"cd-pill cd-lv-Experienced\">Experienced<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Database design<\/span><\/div><h3 class=\"cd-q-title\">92. What is BCNF, and when should you denormalize?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p><strong>Boyce-Codd Normal Form (BCNF)<\/strong> is a stricter 3NF: for every functional dependency X \u2192 Y, X must be a super key. It catches rare cases 3NF allows, such as a table where a non-key column determines part of a composite key (for example, each instructor teaches one subject, but a subject has several instructors).<\/p>\n<p>Denormalize when read performance matters more than write simplicity: reporting tables, data warehouses, search indexes, or pre-computed counters like <code>order_count<\/code> on a customers table. Do it deliberately, and keep the redundant data in sync with triggers, application code or scheduled jobs.<\/p><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-93\" data-level=\"Experienced\" data-type=\"Concept\" data-topic=\"Database design\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q93<\/span><span class=\"cd-pill cd-lv-Experienced\">Experienced<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Database design<\/span><\/div><h3 class=\"cd-q-title\">93. What are fact and dimension tables? Star vs snowflake schema?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>In a data warehouse, a <strong>fact table<\/strong> stores measurable events (sales amount, quantity, clicks) with foreign keys to <strong>dimension tables<\/strong>, which hold descriptive context (date, customer, product, store).<\/p>\n<ul><li><strong>Star schema:<\/strong> one central fact table joined directly to denormalized dimension tables. Fewer joins, simpler and faster queries, and the most common choice.<\/li>\n<li><strong>Snowflake schema:<\/strong> dimensions are normalized into sub-tables (product \u2192 category \u2192 department). Less redundancy, but more joins.<\/li><\/ul>\n<p>Expect this question in data engineer and data analyst interviews, along with slowly changing dimensions (SCD Type 1 overwrites, Type 2 keeps history rows).<\/p><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-94\" data-level=\"Experienced\" data-type=\"Concept\" data-topic=\"Database design\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q94<\/span><span class=\"cd-pill cd-lv-Experienced\">Experienced<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Database design<\/span><\/div><h3 class=\"cd-q-title\">94. What is the difference between partitioning and sharding?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p><strong>Partitioning<\/strong> splits one large table into smaller pieces <strong>within the same database server<\/strong>, by range (order_date by month), list (region) or hash. Queries that filter on the partition key read only the relevant partitions (&#8220;partition pruning&#8221;), and old data can be dropped quickly by partition.<\/p>\n<p><strong>Sharding<\/strong> splits data across <strong>multiple database servers<\/strong>, for example users with ids 1 to 1M on server A and the rest on server B. It scales writes and storage horizontally, but makes cross-shard joins, transactions and rebalancing much harder, so it is used only when one server cannot cope.<\/p><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-95\" data-level=\"Experienced\" data-type=\"Concept\" data-topic=\"Database design\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q95<\/span><span class=\"cd-pill cd-lv-Experienced\">Experienced<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Database design<\/span><\/div><h3 class=\"cd-q-title\">95. When would you choose SQL over NoSQL, and vice versa?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><table><thead><tr><th><\/th><th>SQL (relational)<\/th><th>NoSQL<\/th><\/tr><\/thead><tbody>\n<tr><td>Data model<\/td><td>Tables with a fixed schema<\/td><td>Documents, key-value, wide-column, graph<\/td><\/tr>\n<tr><td>Consistency<\/td><td>Strong ACID transactions<\/td><td>Often eventual consistency (varies)<\/td><\/tr>\n<tr><td>Scaling<\/td><td>Mostly vertical, read replicas<\/td><td>Designed for horizontal scaling<\/td><\/tr>\n<tr><td>Queries<\/td><td>Powerful joins and aggregations<\/td><td>Fast lookups by key, limited joins<\/td><\/tr>\n<tr><td>Good for<\/td><td>Payments, orders, inventory, anything relational<\/td><td>Catalogues, sessions, logs, real-time feeds<\/td><\/tr>\n<tr><td>Examples<\/td><td>PostgreSQL, MySQL, Oracle<\/td><td>MongoDB, Redis, Cassandra, DynamoDB<\/td><\/tr><\/tbody><\/table>\n<p>Many systems use both: PostgreSQL for orders and payments, Redis for caching and sessions.<\/p><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-96\" data-level=\"Experienced\" data-type=\"Concept\" data-topic=\"Transactions\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q96<\/span><span class=\"cd-pill cd-lv-Experienced\">Experienced<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Transactions<\/span><\/div><h3 class=\"cd-q-title\">96. What is MVCC? What is optimistic vs pessimistic locking?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p><strong>MVCC (Multi-Version Concurrency Control)<\/strong>, used by PostgreSQL, MySQL InnoDB and Oracle, keeps several versions of a row. Readers see a consistent snapshot without blocking writers, and writers do not block readers. Old versions are cleaned up later (VACUUM in PostgreSQL, the undo log purge in InnoDB).<\/p>\n<ul><li><strong>Pessimistic locking<\/strong> locks the row before changing it (<code>SELECT ... FOR UPDATE<\/code>), assuming conflicts are likely. Safe, but reduces concurrency.<\/li>\n<li><strong>Optimistic locking<\/strong> does not lock. It checks at update time that nobody else changed the row, usually with a version column: <code>UPDATE ... SET qty = 5, version = version + 1 WHERE id = 7 AND version = 3<\/code>. If 0 rows are updated, retry. Best when conflicts are rare.<\/li><\/ul><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-97\" data-level=\"Experienced\" data-type=\"Concept\" data-topic=\"Security\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q97<\/span><span class=\"cd-pill cd-lv-Experienced\">Experienced<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Security<\/span><\/div><h3 class=\"cd-q-title\">97. What is SQL injection, and how do you prevent it?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>SQL injection happens when user input is pasted directly into a SQL string, letting an attacker change the query. If a login query is built as <code>\"... WHERE user = '\" + input + \"'\"<\/code> and the input is <code>' OR '1'='1<\/code>, the condition is always true and the attacker logs in without a password. It can also be used to read or delete entire tables.<\/p>\n<p>Prevention:<\/p>\n<ul><li><strong>Always use parameterised queries<\/strong> (prepared statements), where input is sent separately from the SQL text, for example <code>cursor.execute(\"SELECT * FROM users WHERE email = %s\", (email,))<\/code>.<\/li>\n<li>Use an ORM or query builder that parameterises for you.<\/li>\n<li>Give the application database user the least privileges it needs.<\/li>\n<li>Validate input types and lengths, and never show raw database errors to users.<\/li><\/ul><div class=\"cdai cd-codebox\"><div class=\"cd-codehead\"><span>SQL \u00b7 syntax example<\/span><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><pre><code>-- Vulnerable: input concatenated into the query\nSELECT * FROM users WHERE email = &#x27;&#x27; OR &#x27;1&#x27;=&#x27;1&#x27;;\n\n-- Safe: placeholder, value bound separately by the driver\nSELECT * FROM users WHERE email = ?;<\/code><\/pre><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-98\" data-level=\"Experienced\" data-type=\"Concept\" data-topic=\"Views\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q98<\/span><span class=\"cd-pill cd-lv-Experienced\">Experienced<\/span><span class=\"cd-pill cd-ty-Concept\">Concept<\/span><span class=\"cd-pill\">Views<\/span><\/div><h3 class=\"cd-q-title\">98. What is a materialized view, and how is it different from a view?<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>A normal view stores only the query, and runs it every time you read from the view. A <strong>materialized view<\/strong> stores the query&#8217;s <strong>result<\/strong> physically, like a table, so reads are very fast. The data can become stale and must be refreshed, on a schedule or on demand (<code>REFRESH MATERIALIZED VIEW<\/code> in PostgreSQL). Oracle can refresh automatically; SQL Server&#8217;s equivalent is an indexed view; MySQL has none, so people use summary tables updated by jobs. Use them for expensive aggregations behind dashboards.<\/p><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-99\" data-level=\"Experienced\" data-type=\"Query\" data-topic=\"Query practice\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q99<\/span><span class=\"cd-pill cd-lv-Experienced\">Experienced<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Query practice<\/span><\/div><h3 class=\"cd-q-title\">99. Split customers into spending quartiles with NTILE.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p><code>NTILE(n)<\/code> divides ordered rows into n roughly equal buckets and returns the bucket number. It is used for segmentation (top 25% customers), percentile-based pricing and A\/B group assignment. Here bucket 1 holds the highest spenders.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>WITH spend AS (\n  SELECT customer_id, SUM(amount) AS total\n  FROM orders WHERE status = &#x27;Delivered&#x27;\n  GROUP BY customer_id\n)\nSELECT customer_id, total,\n       NTILE(4) OVER (ORDER BY total DESC) AS quartile\nFROM spend\nORDER BY total DESC;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\ncustomer_id | total | quartile\n------------+-------+---------\n101         | 11800 | 1\n102         | 7200  | 1\n104         | 5600  | 2\n106         | 4300  | 2\n103         | 2700  | 3\n999         | 1000  | 3\n107         | 600   | 4\n(7 rows)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<section class=\"cdai cd-q\" id=\"q-100\" data-level=\"Experienced\" data-type=\"Query\" data-topic=\"Query practice\"><div class=\"cd-q-meta\"><span class=\"cd-pill\">Q100<\/span><span class=\"cd-pill cd-lv-Experienced\">Experienced<\/span><span class=\"cd-pill cd-ty-Query\">Query<\/span><span class=\"cd-pill\">Query practice<\/span><\/div><h3 class=\"cd-q-title\">100. Find customers whose order amount increased with every order.<\/h3><button type=\"button\" class=\"cd-btn cd-show\">Show answer<\/button><div class=\"cd-q-body\"><p>Compare each order with the customer&#8217;s previous one using LAG, flag any order that did not increase, and keep customers with no such flag and at least two orders. Scenario questions like this test whether you can combine window functions with aggregation in clean steps.<\/p><div class=\"cdai cd-codebox\" data-run=\"1\"><div class=\"cd-codehead\"><span>SQL \u00b7 runs on the sample database<\/span><div class=\"cd-acts\"><button type=\"button\" class=\"cd-run\">\u25b6 Run<\/button><button type=\"button\" class=\"cd-edit\">Edit<\/button><button type=\"button\" class=\"cd-reset\" hidden>Reset<\/button><button type=\"button\" class=\"cd-copy\">Copy<\/button><\/div><\/div><pre><code>WITH seq AS (\n  SELECT customer_id, amount,\n         LAG(amount) OVER (PARTITION BY customer_id ORDER BY order_date) AS prev\n  FROM orders\n  WHERE status = &#x27;Delivered&#x27;\n)\nSELECT customer_id\nFROM seq\nGROUP BY customer_id\nHAVING COUNT(*) &gt;= 2\n   AND SUM(CASE WHEN prev IS NOT NULL AND amount &lt;= prev THEN 1 ELSE 0 END) = 0;<\/code><\/pre><pre class=\"cd-outp\"><code>Output:\ncustomer_id\n-----------\n102\n(1 row)<\/code><\/pre><div class=\"cd-live\" hidden><\/div><\/div><\/div><div class=\"cd-q-foot\"><button type=\"button\" class=\"cd-btn cd-known\" aria-pressed=\"false\">Mark as known<\/button><a class=\"cd-q-top\" href=\"#cd-pyq-tool\">\u2191 Back to filters<\/a><\/div><\/section>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"tricky-sql-queries\">Predict the result: 12 tricky SQL queries<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">These short queries catch even experienced developers, mostly because of NULLs, joins and integer division. Each one was run on the sample database above. Pick what you think it returns.<\/p>\n\n\n\n<div class=\"cdai cd-pyq-predict\"><span class=\"cd-tag\">Game<\/span><h4 class=\"cd-h\">What does this query return?<\/h4>\n<div class=\"cd-pp-body\"><p class=\"cd-sub\">12 queries. Most people get 6 or 7 right on the first try.<\/p><button type=\"button\" class=\"cd-btn cd-primary cd-pp-start\">Start the challenge<\/button><\/div><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"sql-interview-questions-pdf\">Download all 100 SQL interview questions as a PDF<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The PDF has the same 100 questions, answers, queries and outputs, plus the sample database, in a printable format with a clickable table of contents. Revise offline, on your phone, or print it before your interview. It is free, with no sign-up.<\/p>\n\n\n\n<div class=\"cdai\" style=\"display:flex;flex-wrap:wrap;gap:16px;align-items:center;justify-content:space-between\">\n<div style=\"min-width:0\"><span class=\"cd-tag\">Free PDF<\/span><h4 class=\"cd-h\">100 SQL Interview Questions and Answers<\/h4><p class=\"cd-sub\" style=\"margin:0\">Freshers, intermediate and experienced \u00b7 Queries with real outputs \u00b7 Sample database included<\/p><\/div>\n<a class=\"cd-btn cd-dl\" href=\"https:\/\/codeanddebug.in\/blog\/wp-content\/uploads\/2026\/10\/sql-interview-questions-code-and-debug.pdf\" download>Download PDF<\/a><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"faq\">Frequently asked questions<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">What SQL questions are asked in interviews for freshers?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Freshers are mostly asked about SQL command types, primary and foreign keys, the difference between DELETE, TRUNCATE and DROP, WHERE vs HAVING, NULL handling, joins, GROUP BY, normalization and simple queries like the second highest salary, finding duplicates and customers with no orders. Questions 1 to 40 cover all of these.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What are the most common SQL query questions in interviews?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The most common are: Nth highest salary, finding and deleting duplicates, employees earning more than their managers, top N records per group, customers with no orders, running totals, month-over-month growth, and department-wise aggregates. All of them are on this page with queries you can run.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What SQL topics should experienced candidates prepare?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Experienced candidates should prepare window functions in depth, recursive CTEs, query optimization and execution plans, indexing strategy, transaction isolation levels, deadlocks and locking, normalization trade-offs, and data warehouse concepts like star schemas and partitioning.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Which SQL should I learn for interviews: MySQL, PostgreSQL or SQL Server?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The core SQL is the same in all of them, so learn standard SQL first. Then learn the differences for your target company&#8217;s database, mainly LIMIT vs TOP, date functions, string concatenation and auto-increment syntax. The answers on this page point these out.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Is there a PDF of these SQL interview questions?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Yes. All 100 questions with answers, queries, outputs and the sample database are available as a free PDF. Use the Download PDF button on this page. No sign-up is needed.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How can I practise SQL queries online for free?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use the SQL playground on this page: it runs a real SQL engine in your browser on the sample database, and every query question has a Run button. For more practice, solve the SQL problems on LeetCode and HackerRank.<\/p>\n\n\n\n<script type=\"application\/ld+json\">{\"@context\": \"https:\/\/schema.org\", \"@type\": \"FAQPage\", \"mainEntity\": [{\"@type\": \"Question\", \"name\": \"What SQL questions are asked in interviews for freshers?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Freshers are mostly asked about SQL command types, primary and foreign keys, the difference between DELETE, TRUNCATE and DROP, WHERE vs HAVING, NULL handling, joins, GROUP BY, normalization and simple queries like the second highest salary, finding duplicates and customers with no orders. Questions 1 to 40 cover all of these.\"}}, {\"@type\": \"Question\", \"name\": \"What are the most common SQL query questions in interviews?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"The most common are: Nth highest salary, finding and deleting duplicates, employees earning more than their managers, top N records per group, customers with no orders, running totals, month-over-month growth, and department-wise aggregates. All of them are on this page with queries you can run.\"}}, {\"@type\": \"Question\", \"name\": \"What SQL topics should experienced candidates prepare?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Experienced candidates should prepare window functions in depth, recursive CTEs, query optimization and execution plans, indexing strategy, transaction isolation levels, deadlocks and locking, normalization trade-offs, and data warehouse concepts like star schemas and partitioning.\"}}, {\"@type\": \"Question\", \"name\": \"Which SQL should I learn for interviews: MySQL, PostgreSQL or SQL Server?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"The core SQL is the same in all of them, so learn standard SQL first. Then learn the differences for your target company's database, mainly LIMIT vs TOP, date functions, string concatenation and auto-increment syntax. The answers on this page point these out.\"}}, {\"@type\": \"Question\", \"name\": \"Is there a PDF of these SQL interview questions?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Yes. All 100 questions with answers, queries, outputs and the sample database are available as a free PDF. Use the Download PDF button on this page. No sign-up is needed.\"}}, {\"@type\": \"Question\", \"name\": \"How can I practise SQL queries online for free?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Use the SQL playground on this page: it runs a real SQL engine in your browser on the sample database, and every query question has a Run button. For more practice, solve the SQL problems on LeetCode and HackerRank.\"}}]}<\/script>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"next-steps\">Next steps<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Turn on practice mode, go one level at a time, and run every query yourself before you mark it as known. If you are preparing for developer roles, continue with our <a href=\"https:\/\/codeanddebug.in\/blog\/python-interview-questions\/\">Python interview questions<\/a> and the <a href=\"https:\/\/codeanddebug.in\/blog\/dsa-interview-cheat-sheet\/\">DSA interview cheat sheet<\/a>. For data roles, the <a href=\"https:\/\/codeanddebug.in\/blog\/pandas-python-roadmap\/\">Pandas roadmap<\/a> is the natural next step after SQL. All the best for your interview.<\/p>\n\n\n\n<script src=\"data:text\/javascript;charset=utf-8;base64,d2luZG93LkNEX1BSRUQ9W3siY29kZSI6ICJTRUxFQ1QgQ09VTlQoKikgRlJPTSBlbXBsb3llZXMgV0hFUkUgZGVwdF9pZCA8PiAxOyIsICJhbnN3ZXIiOiAiOCIsICJ3aHkiOiAiTWFuaXNoJ3MgZGVwdF9pZCBpcyBOVUxMLCBhbmQgTlVMTCA8PiAxIGlzIFVOS05PV04sIHNvIGhpcyByb3cgaXMgZXhjbHVkZWQgdG9vLiAxNCByb3dzIG1pbnVzIDUgaW4gRW5naW5lZXJpbmcgbWludXMgTWFuaXNoIGxlYXZlcyA4LiIsICJ3cm9uZyI6IFsiOSIsICIxNCIsICIxMyJdfSwgeyJjb2RlIjogIlNFTEVDVCBOVUxMID0gTlVMTCwgTlVMTCBJUyBOVUxMOyIsICJhbnN3ZXIiOiAiTlVMTCB8IDEiLCAid2h5IjogIkNvbXBhcmluZyBOVUxMIHdpdGggPSBnaXZlcyBOVUxMICh1bmtub3duKSwgbmV2ZXIgdHJ1ZS4gT25seSBJUyBOVUxMIHJldHVybnMgMSAodHJ1ZSkuIiwgIndyb25nIjogWyIxIHwgMSIsICIwIHwgMSIsICJOVUxMIHwgTlVMTCJdfSwgeyJjb2RlIjogIlNFTEVDVCBDT1VOVChkZXB0X2lkKSwgQ09VTlQoKikgRlJPTSBlbXBsb3llZXM7IiwgImFuc3dlciI6ICIxMyB8IDE0IiwgIndoeSI6ICJDT1VOVChjb2x1bW4pIHNraXBzIE5VTExzLCBDT1VOVCgqKSBkb2VzIG5vdC4iLCAid3JvbmciOiBbIjE0IHwgMTQiLCAiMTMgfCAxMyIsICIxNCB8IDEzIl19LCB7ImNvZGUiOiAiU0VMRUNUIENPVU5UKCopIEZST00gZGVwYXJ0bWVudHNcbldIRVJFIGRlcHRfaWQgTk9UIElOIChTRUxFQ1QgZGVwdF9pZCBGUk9NIGVtcGxveWVlcyk7IiwgImFuc3dlciI6ICIwIiwgIndoeSI6ICJUaGUgc3VicXVlcnkgY29udGFpbnMgYSBOVUxMLCBzbyBOT1QgSU4gY2FuIG5ldmVyIGJlIHRydWUuIFVzZSBOT1QgRVhJU1RTIGluc3RlYWQuIiwgIndyb25nIjogWyIxIiwgIjUiLCAiRXJyb3IiXX0sIHsiY29kZSI6ICJTRUxFQ1QgQ09VTlQoRElTVElOQ1QgZC5kZXB0X2lkKSBGUk9NIGRlcGFydG1lbnRzIGRcbkxFRlQgSk9JTiBlbXBsb3llZXMgZSBPTiBlLmRlcHRfaWQgPSBkLmRlcHRfaWRcbldIRVJFIGUuc2FsYXJ5ID4gMTAwMDAwOyIsICJhbnN3ZXIiOiAiMyIsICJ3aHkiOiAiTWFueSBleHBlY3QgNSwgc2luY2UgYSBMRUZUIEpPSU4ga2VlcHMgZXZlcnkgZGVwYXJ0bWVudC4gQnV0IHRoZSBXSEVSRSBjb25kaXRpb24gb24gdGhlIHJpZ2h0IHRhYmxlIHJlbW92ZXMgdGhlIHJvd3Mgd2hlcmUgZS5zYWxhcnkgaXMgTlVMTCwgc28gaXQgYmVoYXZlcyBsaWtlIGFuIElOTkVSIEpPSU4uIE9ubHkgMyBkZXBhcnRtZW50cyBoYXZlIHNvbWVvbmUgYWJvdmUgMTAwMDAwLiBNb3ZlIHRoZSBmaWx0ZXIgaW50byB0aGUgT04gY2xhdXNlIHRvIGtlZXAgYWxsIDUuIiwgIndyb25nIjogWyI1IiwgIjEzIiwgIjQiXX0sIHsiY29kZSI6ICJTRUxFQ1QgNyAvIDIsIDcgLyAyLjA7IiwgImFuc3dlciI6ICIzIHwgMy41IiwgIndoeSI6ICJJbnRlZ2VyIGRpdmlkZWQgYnkgaW50ZWdlciBnaXZlcyBhbiBpbnRlZ2VyIGluIFNRTGl0ZSwgUG9zdGdyZVNRTCBhbmQgU1FMIFNlcnZlci4gTXlTUUwgd291bGQgcmV0dXJuIDMuNTAwMCBmb3IgNyAvIDIuIiwgIndyb25nIjogWyIzLjUgfCAzLjUiLCAiMyB8IDMiLCAiNCB8IDMuNSJdfSwgeyJjb2RlIjogIlNFTEVDVCBDT1VOVCgqKSBGUk9NIChcbiAgU0VMRUNUIGNpdHkgRlJPTSBlbXBsb3llZXNcbiAgVU5JT05cbiAgU0VMRUNUIGNpdHkgRlJPTSBlbXBsb3llZXNcbik7IiwgImFuc3dlciI6ICI3IiwgIndoeSI6ICJVTklPTiByZW1vdmVzIGR1cGxpY2F0ZXMsIHNvIHlvdSBnZXQgdGhlIDcgZGlzdGluY3QgY2l0aWVzLCBub3QgMjggcm93cy4iLCAid3JvbmciOiBbIjI4IiwgIjE0IiwgIkVycm9yIl19LCB7ImNvZGUiOiAiU0VMRUNUIEFWRyh4KSBGUk9NIChTRUxFQ1QgMTAgQVMgeCBVTklPTiBBTEwgU0VMRUNUIE5VTEwgVU5JT04gQUxMIFNFTEVDVCAyMCk7IiwgImFuc3dlciI6ICIxNSIsICJ3aHkiOiAiQVZHIGlnbm9yZXMgTlVMTHMsIHNvIGl0IGlzICgxMCArIDIwKSAvIDIsIG5vdCBkaXZpZGVkIGJ5IDMuIiwgIndyb25nIjogWyIxMCIsICJOVUxMIiwgIjIwIl19LCB7ImNvZGUiOiAiU0VMRUNUIE1BWChuYW1lKSBGUk9NIGVtcGxveWVlczsiLCAiYW5zd2VyIjogIlZpa3JhbSBKb3NoaSIsICJ3aHkiOiAiTUFYIHdvcmtzIG9uIHRleHQgdG9vLCB1c2luZyBhbHBoYWJldGljYWwgb3JkZXIuICdWaWtyYW0gSm9zaGknIHNvcnRzIGxhc3QuIiwgIndyb25nIjogWyJSYWplc2ggS3VtYXIiLCAiRGl2eWEgTWVub24iLCAiRXJyb3IiXX0sIHsiY29kZSI6ICJTRUxFQ1QgZGVwdF9pZCwgQ09VTlQoKikgRlJPTSBlbXBsb3llZXNcbkdST1VQIEJZIGRlcHRfaWRcbkhBVklORyBDT1VOVCgqKSA+IDQ7IiwgImFuc3dlciI6ICIxIHwgNSIsICJ3aHkiOiAiT25seSBFbmdpbmVlcmluZyAoZGVwdCAxKSBoYXMgbW9yZSB0aGFuIDQgZW1wbG95ZWVzLiIsICJ3cm9uZyI6IFsiMiB8IDQiLCAiTm8gcm93cyIsICIxIHwgNVxuMiB8IDQiXX0sIHsiY29kZSI6ICJTRUxFQ1QgQ09BTEVTQ0UoTlVMTCwgTlVMTCwgJ3gnLCAneScpOyIsICJhbnN3ZXIiOiAieCIsICJ3aHkiOiAiQ09BTEVTQ0UgcmV0dXJucyB0aGUgZmlyc3Qgbm9uLU5VTEwgYXJndW1lbnQuIiwgIndyb25nIjogWyJOVUxMIiwgInkiLCAieCwgeSJdfSwgeyJjb2RlIjogIlNFTEVDVCBuYW1lIEZST00gZW1wbG95ZWVzIE9SREVSIEJZIHNhbGFyeSBERVNDIExJTUlUIDEgT0ZGU0VUIDI7IiwgImFuc3dlciI6ICJLYXJhbiBNZWh0YSIsICJ3aHkiOiAiT0ZGU0VUIDIgc2tpcHMgdGhlIGZpcnN0IHR3byByb3dzLiBLYXJhbiBhbmQgS2F2eWEgdGllIGF0IDEyMDAwMCwgYW5kIFNRTGl0ZSByZXR1cm5zIEthcmFuIGhlcmUsIGJ1dCB3aXRoIHRpZXMgdGhlIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkIGluIGdlbmVyYWwuIiwgIndyb25nIjogWyJQcml5YSBTaGFybWEiLCAiS2F2eWEgUmVkZHkiLCAiUG9vamEgTmFpciJdfV07CndpbmRvdy5DRF9TRUVEPSJDUkVBVEUgVEFCTEUgZGVwYXJ0bWVudHMgKFxuICBkZXB0X2lkICAgSU5URUdFUiBQUklNQVJZIEtFWSxcbiAgZGVwdF9uYW1lIFRFWFQgTk9UIE5VTEwsXG4gIGxvY2F0aW9uICBURVhUXG4pO1xuSU5TRVJUIElOVE8gZGVwYXJ0bWVudHMgVkFMVUVTXG4gKDEsICdFbmdpbmVlcmluZycsICdCZW5nYWx1cnUnKSxcbiAoMiwgJ1NhbGVzJywgJ011bWJhaScpLFxuICgzLCAnSFInLCAnUHVuZScpLFxuICg0LCAnRmluYW5jZScsICdNdW1iYWknKSxcbiAoNSwgJ01hcmtldGluZycsICdEZWxoaScpO1xuXG5DUkVBVEUgVEFCTEUgZW1wbG95ZWVzIChcbiAgZW1wX2lkICAgICBJTlRFR0VSIFBSSU1BUlkgS0VZLFxuICBuYW1lICAgICAgIFRFWFQgTk9UIE5VTEwsXG4gIGRlcHRfaWQgICAgSU5URUdFUiBSRUZFUkVOQ0VTIGRlcGFydG1lbnRzKGRlcHRfaWQpLFxuICBtYW5hZ2VyX2lkIElOVEVHRVIgUkVGRVJFTkNFUyBlbXBsb3llZXMoZW1wX2lkKSxcbiAgc2FsYXJ5ICAgICBJTlRFR0VSLFxuICBoaXJlX2RhdGUgIFRFWFQsXG4gIGNpdHkgICAgICAgVEVYVFxuKTtcbklOU0VSVCBJTlRPIGVtcGxveWVlcyBWQUxVRVNcbiAoMSwgJ1JhamVzaCBLdW1hcicsIDEsIE5VTEwsIDI1MDAwMCwgJzIwMTUtMDQtMDEnLCAnQmVuZ2FsdXJ1JyksXG4gKDIsICdQcml5YSBTaGFybWEnLCAxLCAxLCAxNTAwMDAsICcyMDE3LTA2LTE1JywgJ0JlbmdhbHVydScpLFxuICgzLCAnQW1pdCBWZXJtYScsIDEsIDIsIDk1MDAwLCAnMjAxOS0wMS0xMCcsICdIeWRlcmFiYWQnKSxcbiAoNCwgJ1NuZWhhIEl5ZXInLCAxLCAyLCA5NTAwMCwgJzIwMjAtMDMtMjInLCAnQmVuZ2FsdXJ1JyksXG4gKDUsICdLYXJhbiBNZWh0YScsIDIsIDEsIDEyMDAwMCwgJzIwMTYtMDktMDUnLCAnTXVtYmFpJyksXG4gKDYsICdOZWhhIEd1cHRhJywgMiwgNSwgNzAwMDAsICcyMDIxLTA3LTE5JywgJ011bWJhaScpLFxuICg3LCAnUm9oaXQgU2luZ2gnLCAyLCA1LCA2NTAwMCwgJzIwMjItMDItMTQnLCAnRGVsaGknKSxcbiAoOCwgJ0FuYW55YSBSYW8nLCAzLCAxLCA4NTAwMCwgJzIwMTgtMTEtMzAnLCAnUHVuZScpLFxuICg5LCAnVmlrcmFtIEpvc2hpJywgMywgOCwgNTUwMDAsICcyMDIzLTA1LTA4JywgJ1B1bmUnKSxcbiAoMTAsICdQb29qYSBOYWlyJywgNCwgMSwgMTEwMDAwLCAnMjAxNy0wMS0yNScsICdNdW1iYWknKSxcbiAoMTEsICdBcmp1biBQYXRlbCcsIDQsIDEwLCA3NTAwMCwgJzIwMjAtMDgtMTcnLCAnQWhtZWRhYmFkJyksXG4gKDEyLCAnS2F2eWEgUmVkZHknLCAxLCAyLCAxMjAwMDAsICcyMDE4LTA0LTEyJywgJ0h5ZGVyYWJhZCcpLFxuICgxMywgJ01hbmlzaCBUaXdhcmknLCBOVUxMLCA1LCA0ODAwMCwgJzIwMjQtMDEtMTUnLCAnTHVja25vdycpLFxuICgxNCwgJ0RpdnlhIE1lbm9uJywgMiwgNiwgNzIwMDAsICcyMDI0LTA2LTAxJywgJ011bWJhaScpO1xuXG5DUkVBVEUgVEFCTEUgY3VzdG9tZXJzIChcbiAgY3VzdG9tZXJfaWQgSU5URUdFUiBQUklNQVJZIEtFWSxcbiAgbmFtZSAgICAgICAgVEVYVCBOT1QgTlVMTCxcbiAgZW1haWwgICAgICAgVEVYVCxcbiAgY2l0eSAgICAgICAgVEVYVCxcbiAgc2lnbnVwX2RhdGUgVEVYVFxuKTtcbklOU0VSVCBJTlRPIGN1c3RvbWVycyBWQUxVRVNcbiAoMTAxLCAnQWFyYXYgU2hhaCcsICdhYXJhdkBtYWlsLmNvbScsICdTdXJhdCcsICcyMDI1LTAxLTEyJyksXG4gKDEwMiwgJ0lzaGEgS2Fwb29yJywgJ2lzaGFAbWFpbC5jb20nLCAnRGVsaGknLCAnMjAyNS0wMi0wMycpLFxuICgxMDMsICdZYXNoIE1hbGhvdHJhJywgJ3lhc2hAbWFpbC5jb20nLCAnTXVtYmFpJywgJzIwMjUtMDItMjAnKSxcbiAoMTA0LCAnTWVlcmEgUGlsbGFpJywgJ21lZXJhQG1haWwuY29tJywgJ0tvY2hpJywgJzIwMjUtMDMtMTUnKSxcbiAoMTA1LCAnRGV2IENob3VkaGFyeScsICdkZXZAbWFpbC5jb20nLCAnSmFpcHVyJywgJzIwMjUtMDQtMDEnKSxcbiAoMTA2LCAnUml5YSBTZW4nLCAncml5YUBtYWlsLmNvbScsICdLb2xrYXRhJywgJzIwMjUtMDUtMDknKSxcbiAoMTA3LCAnQWFyYXYgU2hhaCcsICdhYXJhdkBtYWlsLmNvbScsICdTdXJhdCcsICcyMDI1LTA2LTIxJyksXG4gKDEwOCwgJ1RhcmEgQm9zZScsIE5VTEwsICdLb2xrYXRhJywgJzIwMjUtMDctMzAnKTtcblxuQ1JFQVRFIFRBQkxFIG9yZGVycyAoXG4gIG9yZGVyX2lkICAgIElOVEVHRVIgUFJJTUFSWSBLRVksXG4gIGN1c3RvbWVyX2lkIElOVEVHRVIsXG4gIG9yZGVyX2RhdGUgIFRFWFQsXG4gIGFtb3VudCAgICAgIElOVEVHRVIsXG4gIHN0YXR1cyAgICAgIFRFWFRcbik7XG5JTlNFUlQgSU5UTyBvcmRlcnMgVkFMVUVTXG4gKDEsIDEwMSwgJzIwMjUtMDEtMTUnLCAyNTAwLCAnRGVsaXZlcmVkJyksXG4gKDIsIDEwMiwgJzIwMjUtMDItMDUnLCAxMjAwLCAnRGVsaXZlcmVkJyksXG4gKDMsIDEwMSwgJzIwMjUtMDItMTgnLCAzNDAwLCAnRGVsaXZlcmVkJyksXG4gKDQsIDEwMywgJzIwMjUtMDMtMDInLCA4MDAsICdDYW5jZWxsZWQnKSxcbiAoNSwgMTA0LCAnMjAyNS0wMy0yMCcsIDU2MDAsICdEZWxpdmVyZWQnKSxcbiAoNiwgMTAyLCAnMjAyNS0wMy0yNScsIDIxMDAsICdEZWxpdmVyZWQnKSxcbiAoNywgMTA1LCAnMjAyNS0wNC0xMCcsIDk1MCwgJ1BlbmRpbmcnKSxcbiAoOCwgMTAxLCAnMjAyNS0wNC0yMicsIDE4MDAsICdEZWxpdmVyZWQnKSxcbiAoOSwgMTA2LCAnMjAyNS0wNS0xMScsIDQzMDAsICdEZWxpdmVyZWQnKSxcbiAoMTAsIDEwMywgJzIwMjUtMDUtMjgnLCAyNzAwLCAnRGVsaXZlcmVkJyksXG4gKDExLCAxMDQsICcyMDI1LTA2LTA1JywgMTUwMCwgJ0NhbmNlbGxlZCcpLFxuICgxMiwgMTAyLCAnMjAyNS0wNi0xOScsIDM5MDAsICdEZWxpdmVyZWQnKSxcbiAoMTMsIDEwNywgJzIwMjUtMDYtMjUnLCA2MDAsICdEZWxpdmVyZWQnKSxcbiAoMTQsIDEwNiwgJzIwMjUtMDctMDgnLCAyMjAwLCAnUGVuZGluZycpLFxuICgxNSwgOTk5LCAnMjAyNS0wNy0xMicsIDEwMDAsICdEZWxpdmVyZWQnKSxcbiAoMTYsIDEwMSwgJzIwMjUtMDctMzAnLCA0MTAwLCAnRGVsaXZlcmVkJyk7XG4iOwooZnVuY3Rpb24oKXsKInVzZSBzdHJpY3QiOwpmdW5jdGlvbiAkKHMscil7cmV0dXJuIChyfHxkb2N1bWVudCkucXVlcnlTZWxlY3RvcihzKX0KZnVuY3Rpb24gJCQocyxyKXtyZXR1cm4gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoKHJ8fGRvY3VtZW50KS5xdWVyeVNlbGVjdG9yQWxsKHMpKX0KZnVuY3Rpb24gc3RvcmUoayx2KXt0cnl7aWYodj09PXVuZGVmaW5lZClyZXR1cm4gSlNPTi5wYXJzZShsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgiY2RzcWxfIitrKSk7bG9jYWxTdG9yYWdlLnNldEl0ZW0oImNkc3FsXyIrayxKU09OLnN0cmluZ2lmeSh2KSl9Y2F0Y2goZSl7cmV0dXJuIG51bGx9fQp2YXIgUXM9JCQoIi5jZGFpLmNkLXEiKSx0b29sPSQoIi5jZGFpLmNkLXB5cS10b29sIik7CnZhciBrbm93bj1zdG9yZSgia25vd24iKXx8e307CnZhciBzdGF0ZT17bGV2ZWw6ImFsbCIsdHlwZToiYWxsIix0b3BpYzoiYWxsIixzZWFyY2g6IiIscHJhY3RpY2U6ZmFsc2UsaGlkZUtub3duOmZhbHNlfTsKCi8qIHBlci1xdWVzdGlvbiBjb250cm9scyAqLwpRcy5mb3JFYWNoKGZ1bmN0aW9uKHEpewogdmFyIGlkPXEuaWQsa2I9JCgiLmNkLWtub3duIixxKSxzYj0kKCIuY2Qtc2hvdyIscSk7CiBmdW5jdGlvbiBwYWludCgpe3ZhciBrPSEha25vd25baWRdO3EuY2xhc3NMaXN0LnRvZ2dsZSgiY2QtaXMta25vd24iLGspO2tiLnNldEF0dHJpYnV0ZSgiYXJpYS1wcmVzc2VkIixrPyJ0cnVlIjoiZmFsc2UiKTtrYi50ZXh0Q29udGVudD1rPyLinJMgSSBrbm93IHRoaXMiOiJNYXJrIGFzIGtub3duIn0KIGtiLmFkZEV2ZW50TGlzdGVuZXIoImNsaWNrIixmdW5jdGlvbigpe2lmKGtub3duW2lkXSlkZWxldGUga25vd25baWRdO2Vsc2Uga25vd25baWRdPTE7c3RvcmUoImtub3duIixrbm93bik7cGFpbnQoKTtwcm9ncmVzcygpO2lmKHN0YXRlLmhpZGVLbm93bilhcHBseSgpfSk7CiBzYi5hZGRFdmVudExpc3RlbmVyKCJjbGljayIsZnVuY3Rpb24oKXtxLmNsYXNzTGlzdC5hZGQoImNkLXJldmVhbGVkIil9KTsKIHEuX3BhaW50PXBhaW50O3BhaW50KCk7Cn0pOwoKZnVuY3Rpb24gcHJvZ3Jlc3MoKXt2YXIgbj1Rcy5maWx0ZXIoZnVuY3Rpb24ocSl7cmV0dXJuIGtub3duW3EuaWRdfSkubGVuZ3RoOwogJCQoIi5jZC1weXEta25vd24iKS5mb3JFYWNoKGZ1bmN0aW9uKGUpe2UudGV4dENvbnRlbnQ9bn0pOyQkKCIuY2QtcHlxLWJhciBpIikuZm9yRWFjaChmdW5jdGlvbihlKXtlLnN0eWxlLndpZHRoPShuL1FzLmxlbmd0aCoxMDApKyIlIn0pfQoKZnVuY3Rpb24gdmlzaWJsZVFzKCl7cmV0dXJuIFFzLmZpbHRlcihmdW5jdGlvbihxKXtyZXR1cm4gIXEuaGlkZGVufSl9CmZ1bmN0aW9uIGFwcGx5KCl7CiB2YXIgcz1zdGF0ZS5zZWFyY2gudHJpbSgpLnRvTG93ZXJDYXNlKCksc2hvd249MDsKIFFzLmZvckVhY2goZnVuY3Rpb24ocSl7dmFyIG9rPShzdGF0ZS5sZXZlbD09PSJhbGwifHxxLmRhdGFzZXQubGV2ZWw9PT1zdGF0ZS5sZXZlbCkmJihzdGF0ZS50eXBlPT09ImFsbCJ8fHEuZGF0YXNldC50eXBlPT09c3RhdGUudHlwZSkmJihzdGF0ZS50b3BpYz09PSJhbGwifHxxLmRhdGFzZXQudG9waWM9PT1zdGF0ZS50b3BpYykmJighc3x8cS50ZXh0Q29udGVudC50b0xvd2VyQ2FzZSgpLmluZGV4T2Yocyk+LTEpJiYhKHN0YXRlLmhpZGVLbm93biYma25vd25bcS5pZF0pOwogIHEuaGlkZGVuPSFvaztpZihvaylzaG93bisrO3EuY2xhc3NMaXN0LnRvZ2dsZSgiY2QtcHJhY3RpY2UiLHN0YXRlLnByYWN0aWNlKTtpZighc3RhdGUucHJhY3RpY2UpcS5jbGFzc0xpc3QucmVtb3ZlKCJjZC1yZXZlYWxlZCIpfSk7CiAkJCgiLmNkLXB5cS1zaG93biIpLmZvckVhY2goZnVuY3Rpb24oZSl7ZS50ZXh0Q29udGVudD1zaG93bn0pOwogdmFyIG5vbmU9JCgiLmNkLXB5cS1ub25lIik7aWYobm9uZSlub25lLmhpZGRlbj1zaG93bj4wOwogc3RvcmUoInN0YXRlIix7bGV2ZWw6c3RhdGUubGV2ZWwsdG9waWM6c3RhdGUudG9waWMscHJhY3RpY2U6c3RhdGUucHJhY3RpY2UsaGlkZUtub3duOnN0YXRlLmhpZGVLbm93bn0pOwp9CgppZih0b29sKXsKIHZhciBzYXZlZD1zdG9yZSgic3RhdGUiKTtpZihzYXZlZCl7c3RhdGUubGV2ZWw9c2F2ZWQubGV2ZWx8fCJhbGwiO3N0YXRlLnRvcGljPXNhdmVkLnRvcGljfHwiYWxsIjtzdGF0ZS5wcmFjdGljZT0hIXNhdmVkLnByYWN0aWNlO3N0YXRlLmhpZGVLbm93bj0hIXNhdmVkLmhpZGVLbm93bn0KIHZhciBzZWw9JCgiLmNkLXB5cS10b3BpYyIsdG9vbCksdG9waWNzPXt9O1FzLmZvckVhY2goZnVuY3Rpb24ocSl7dG9waWNzW3EuZGF0YXNldC50b3BpY109KHRvcGljc1txLmRhdGFzZXQudG9waWNdfHwwKSsxfSk7CiBPYmplY3Qua2V5cyh0b3BpY3MpLnNvcnQoKS5mb3JFYWNoKGZ1bmN0aW9uKHQpe3ZhciBvPWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIm9wdGlvbiIpO28udmFsdWU9dDtvLnRleHRDb250ZW50PXQrIiAoIit0b3BpY3NbdF0rIikiO3NlbC5hcHBlbmRDaGlsZChvKX0pOwogc2VsLnZhbHVlPXN0YXRlLnRvcGljO2lmKHNlbC52YWx1ZSE9PXN0YXRlLnRvcGljKXtzdGF0ZS50b3BpYz0iYWxsIjtzZWwudmFsdWU9ImFsbCJ9CiBmdW5jdGlvbiBjaGlwcygpeyQkKCIuY2QtbHZsIix0b29sKS5mb3JFYWNoKGZ1bmN0aW9uKGMpe2Muc2V0QXR0cmlidXRlKCJhcmlhLXByZXNzZWQiLGMuZGF0YXNldC5sPT09c3RhdGUubGV2ZWw\/InRydWUiOiJmYWxzZSIpfSl9CiAkJCgiLmNkLWx2bCIsdG9vbCkuZm9yRWFjaChmdW5jdGlvbihjKXtjLmFkZEV2ZW50TGlzdGVuZXIoImNsaWNrIixmdW5jdGlvbigpe3N0YXRlLmxldmVsPWMuZGF0YXNldC5sO2NoaXBzKCk7YXBwbHkoKX0pfSk7CiBzZWwuYWRkRXZlbnRMaXN0ZW5lcigiY2hhbmdlIixmdW5jdGlvbigpe3N0YXRlLnRvcGljPXNlbC52YWx1ZTthcHBseSgpfSk7CiB2YXIgc2k9JCgiLmNkLXB5cS1zZWFyY2giLHRvb2wpLHQwO3NpLmFkZEV2ZW50TGlzdGVuZXIoImlucHV0IixmdW5jdGlvbigpe2NsZWFyVGltZW91dCh0MCk7dDA9c2V0VGltZW91dChmdW5jdGlvbigpe3N0YXRlLnNlYXJjaD1zaS52YWx1ZTthcHBseSgpfSwxNTApfSk7CiB2YXIgcHI9JCgiLmNkLXB5cS1wcmFjdGljZSIsdG9vbCksaGs9JCgiLmNkLXB5cS1oaWRla25vd24iLHRvb2wpO3ByLmNoZWNrZWQ9c3RhdGUucHJhY3RpY2U7aGsuY2hlY2tlZD1zdGF0ZS5oaWRlS25vd247CiBwci5hZGRFdmVudExpc3RlbmVyKCJjaGFuZ2UiLGZ1bmN0aW9uKCl7c3RhdGUucHJhY3RpY2U9cHIuY2hlY2tlZDthcHBseSgpfSk7CiBoay5hZGRFdmVudExpc3RlbmVyKCJjaGFuZ2UiLGZ1bmN0aW9uKCl7c3RhdGUuaGlkZUtub3duPWhrLmNoZWNrZWQ7YXBwbHkoKX0pOwogJCgiLmNkLXB5cS1yZXNldCIsdG9vbCkuYWRkRXZlbnRMaXN0ZW5lcigiY2xpY2siLGZ1bmN0aW9uKCl7a25vd249e307c3RvcmUoImtub3duIixrbm93bik7UXMuZm9yRWFjaChmdW5jdGlvbihxKXtxLl9wYWludCgpfSk7cHJvZ3Jlc3MoKTthcHBseSgpfSk7CiAkKCIuY2QtcHlxLWZjIix0b29sKS5hZGRFdmVudExpc3RlbmVyKCJjbGljayIsZnVuY3Rpb24oKXtvcGVuQ2FyZHMoKX0pOwogJCQoIi5jZC10eXAiLHRvb2wpLmZvckVhY2goZnVuY3Rpb24oYyl7Yy5hZGRFdmVudExpc3RlbmVyKCJjbGljayIsZnVuY3Rpb24oKXtzdGF0ZS50eXBlPWMuZGF0YXNldC50OyQkKCIuY2QtdHlwIix0b29sKS5mb3JFYWNoKGZ1bmN0aW9uKHgpe3guc2V0QXR0cmlidXRlKCJhcmlhLXByZXNzZWQiLHg9PT1jPyJ0cnVlIjoiZmFsc2UiKX0pO2FwcGx5KCl9KX0pOwogY2hpcHMoKTsKfQpwcm9ncmVzcygpO2FwcGx5KCk7CgovKiBmbGFzaGNhcmRzICovCnZhciBmYz1udWxsLGRlY2s9W10scG9zPTA7CmZ1bmN0aW9uIGJ1aWxkTW9kYWwoKXtmYz1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJkaXYiKTtmYy5jbGFzc05hbWU9ImNkYWkgY2QtZmMiO2ZjLnNldEF0dHJpYnV0ZSgicm9sZSIsImRpYWxvZyIpO2ZjLnNldEF0dHJpYnV0ZSgiYXJpYS1tb2RhbCIsInRydWUiKTtmYy5zZXRBdHRyaWJ1dGUoImFyaWEtbGFiZWwiLCJGbGFzaGNhcmRzIik7CiBmYy5pbm5lckhUTUw9JzxkaXYgY2xhc3M9ImNkLWZjLWNhcmQiPjxkaXYgY2xhc3M9ImNkLXJvdyIgc3R5bGU9Imp1c3RpZnktY29udGVudDpzcGFjZS1iZXR3ZWVuIj48c3BhbiBjbGFzcz0iY2Qtc21hbGwgY2QtZmMtY291bnQiPjwvc3Bhbj48YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImNkLWJ0biBjZC1mYy1jbG9zZSIgYXJpYS1sYWJlbD0iQ2xvc2UgZmxhc2hjYXJkcyI+Q2xvc2Ug4pyVPC9idXR0b24+PC9kaXY+JysKICc8ZGl2IGNsYXNzPSJjZC1mYy1tZXRhIj48L2Rpdj48ZGl2IGNsYXNzPSJjZC1mYy1xIj48L2Rpdj48ZGl2IGNsYXNzPSJjZC1mYy1hIiBoaWRkZW4+PC9kaXY+JysKICc8ZGl2IGNsYXNzPSJjZC1yb3cgY2QtZmMtYWN0aW9ucyI+PGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJjZC1idG4gY2QtcHJpbWFyeSBjZC1mYy1mbGlwIj5TaG93IGFuc3dlcjwvYnV0dG9uPjxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iY2QtYnRuIGNkLWZjLXllcyIgaGlkZGVuPuKckyBJIGtuZXcgaXQ8L2J1dHRvbj48YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImNkLWJ0biBjZC1mYy1ubyIgaGlkZGVuPlN0aWxsIGxlYXJuaW5nPC9idXR0b24+PC9kaXY+JysKICc8ZGl2IGNsYXNzPSJjZC1yb3ciIHN0eWxlPSJqdXN0aWZ5LWNvbnRlbnQ6c3BhY2UtYmV0d2VlbjttYXJnaW4tdG9wOjEwcHgiPjxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iY2QtYnRuIGNkLWZjLXByZXYiPuKGkCBQcmV2aW91czwvYnV0dG9uPjxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iY2QtYnRuIGNkLWZjLXNodWZmbGUiPlNodWZmbGU8L2J1dHRvbj48YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImNkLWJ0biBjZC1mYy1uZXh0Ij5OZXh0IOKGkjwvYnV0dG9uPjwvZGl2PjxkaXYgY2xhc3M9ImNkLXByb2cgY2QtZmMtcHJvZyI+PGk+PC9pPjwvZGl2PjwvZGl2Pic7CiBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGZjKTsKICQoIi5jZC1mYy1jbG9zZSIsZmMpLmFkZEV2ZW50TGlzdGVuZXIoImNsaWNrIixjbG9zZSk7ZmMuYWRkRXZlbnRMaXN0ZW5lcigiY2xpY2siLGZ1bmN0aW9uKGUpe2lmKGUudGFyZ2V0PT09ZmMpY2xvc2UoKX0pOwogJCgiLmNkLWZjLWZsaXAiLGZjKS5hZGRFdmVudExpc3RlbmVyKCJjbGljayIsZmxpcCk7JCgiLmNkLWZjLW5leHQiLGZjKS5hZGRFdmVudExpc3RlbmVyKCJjbGljayIsZnVuY3Rpb24oKXtnbygxKX0pOyQoIi5jZC1mYy1wcmV2IixmYykuYWRkRXZlbnRMaXN0ZW5lcigiY2xpY2siLGZ1bmN0aW9uKCl7Z28oLTEpfSk7CiAkKCIuY2QtZmMteWVzIixmYykuYWRkRXZlbnRMaXN0ZW5lcigiY2xpY2siLGZ1bmN0aW9uKCl7a25vd25bZGVja1twb3NdLmlkXT0xO3N0b3JlKCJrbm93biIsa25vd24pO2RlY2tbcG9zXS5fcGFpbnQoKTtwcm9ncmVzcygpO2dvKDEpfSk7CiAkKCIuY2QtZmMtbm8iLGZjKS5hZGRFdmVudExpc3RlbmVyKCJjbGljayIsZnVuY3Rpb24oKXtkZWxldGUga25vd25bZGVja1twb3NdLmlkXTtzdG9yZSgia25vd24iLGtub3duKTtkZWNrW3Bvc10uX3BhaW50KCk7cHJvZ3Jlc3MoKTtnbygxKX0pOwogJCgiLmNkLWZjLXNodWZmbGUiLGZjKS5hZGRFdmVudExpc3RlbmVyKCJjbGljayIsZnVuY3Rpb24oKXtmb3IodmFyIGk9ZGVjay5sZW5ndGgtMTtpPjA7aS0tKXt2YXIgaj1NYXRoLmZsb29yKE1hdGgucmFuZG9tKCkqKGkrMSkpLHQ9ZGVja1tpXTtkZWNrW2ldPWRlY2tbal07ZGVja1tqXT10fXBvcz0wO3Nob3coKX0pOwogZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigia2V5ZG93biIsZnVuY3Rpb24oZSl7aWYoIWZjfHxmYy5oaWRkZW4pcmV0dXJuO2lmKGUua2V5PT09IkVzY2FwZSIpY2xvc2UoKTtlbHNlIGlmKGUua2V5PT09IkFycm93UmlnaHQiKWdvKDEpO2Vsc2UgaWYoZS5rZXk9PT0iQXJyb3dMZWZ0IilnbygtMSk7ZWxzZSBpZihlLmtleT09PSIgIiYmZS50YXJnZXQudGFnTmFtZSE9PSJCVVRUT04iKXtlLnByZXZlbnREZWZhdWx0KCk7ZmxpcCgpfX0pfQpmdW5jdGlvbiBvcGVuQ2FyZHMoKXtkZWNrPXZpc2libGVRcygpO2lmKCFkZWNrLmxlbmd0aClkZWNrPVFzLnNsaWNlKCk7aWYoIWZjKWJ1aWxkTW9kYWwoKTtmYy5oaWRkZW49ZmFsc2U7cG9zPTA7c2hvdygpOyQoIi5jZC1mYy1mbGlwIixmYykuZm9jdXMoKX0KZnVuY3Rpb24gY2xvc2UoKXtmYy5oaWRkZW49dHJ1ZTt2YXIgYj0kKCIuY2QtcHlxLWZjIik7aWYoYiliLmZvY3VzKCl9CmZ1bmN0aW9uIGdvKGQpe3Bvcz0ocG9zK2QrZGVjay5sZW5ndGgpJWRlY2subGVuZ3RoO3Nob3coKX0KZnVuY3Rpb24gZmxpcCgpe3ZhciBhPSQoIi5jZC1mYy1hIixmYyk7YS5oaWRkZW49ZmFsc2U7JCgiLmNkLWZjLWZsaXAiLGZjKS5oaWRkZW49dHJ1ZTskKCIuY2QtZmMteWVzIixmYykuaGlkZGVuPWZhbHNlOyQoIi5jZC1mYy1ubyIsZmMpLmhpZGRlbj1mYWxzZX0KZnVuY3Rpb24gc2hvdygpe3ZhciBxPWRlY2tbcG9zXTskKCIuY2QtZmMtY291bnQiLGZjKS50ZXh0Q29udGVudD0iQ2FyZCAiKyhwb3MrMSkrIiBvZiAiK2RlY2subGVuZ3RoOwogJCgiLmNkLWZjLW1ldGEiLGZjKS5pbm5lckhUTUw9JCgiLmNkLXEtbWV0YSIscSkuaW5uZXJIVE1MOyQoIi5jZC1mYy1xIixmYykudGV4dENvbnRlbnQ9JCgiLmNkLXEtdGl0bGUiLHEpLnRleHRDb250ZW50OwogdmFyIGE9JCgiLmNkLWZjLWEiLGZjKTthLmlubmVySFRNTD0kKCIuY2QtcS1ib2R5IixxKS5pbm5lckhUTUw7YS5oaWRkZW49dHJ1ZTskJCgiLmNkLWNvcHkiLGEpLmZvckVhY2goZnVuY3Rpb24oYil7Yi5yZW1vdmUoKX0pOwogJCgiLmNkLWZjLWZsaXAiLGZjKS5oaWRkZW49ZmFsc2U7JCgiLmNkLWZjLXllcyIsZmMpLmhpZGRlbj10cnVlOyQoIi5jZC1mYy1ubyIsZmMpLmhpZGRlbj10cnVlOwogJCgiLmNkLWZjLXByb2cgaSIsZmMpLnN0eWxlLndpZHRoPSgocG9zKzEpL2RlY2subGVuZ3RoKjEwMCkrIiUiOyQoIi5jZC1mYy1jYXJkIixmYykuc2Nyb2xsVG9wPTB9CgovKiBwcmVkaWN0IHRoZSBvdXRwdXQgKi8KJCQoIi5jZGFpLmNkLXB5cS1wcmVkaWN0IikuZm9yRWFjaChmdW5jdGlvbihib3gpewogdmFyIFA9d2luZG93LkNEX1BSRUR8fFtdLGk9MCxzY29yZT0wLGJvZHk9JCgiLmNkLXBwLWJvZHkiLGJveCk7CiBmdW5jdGlvbiBlc2Mocyl7cmV0dXJuIHMucmVwbGFjZSgvJi9nLCImYW1wOyIpLnJlcGxhY2UoLzwvZywiJmx0OyIpLnJlcGxhY2UoLz4vZywiJmd0OyIpfQogZnVuY3Rpb24gc2hvdygpe3ZhciBpdD1QW2ldLG9wdHM9aXQud3JvbmcuY29uY2F0KFtpdC5hbnN3ZXJdKTtmb3IodmFyIGs9b3B0cy5sZW5ndGgtMTtrPjA7ay0tKXt2YXIgaj1NYXRoLmZsb29yKE1hdGgucmFuZG9tKCkqKGsrMSkpLHQ9b3B0c1trXTtvcHRzW2tdPW9wdHNbal07b3B0c1tqXT10fQogIGJvZHkuaW5uZXJIVE1MPSc8cCBjbGFzcz0iY2Qtc21hbGwiPlNuaXBwZXQgJysoaSsxKSsnIG9mICcrUC5sZW5ndGgrJyB8IFNjb3JlICcrc2NvcmUrJzwvcD48ZGl2IGNsYXNzPSJjZC1jb2RlYm94IGNkYWkiIHN0eWxlPSJtYXJnaW46OHB4IDAiPjxwcmU+PGNvZGU+Jytlc2MoaXQuY29kZSkrJzwvY29kZT48L3ByZT48L2Rpdj48cCBjbGFzcz0iY2Qtc21hbGwiIHN0eWxlPSJtYXJnaW46NnB4IDAiPldoYXQgZG9lcyB0aGlzIHF1ZXJ5IHJldHVybj8gKE11bHRpcGxlIGNvbHVtbnMgYXJlIHNob3duIHNlcGFyYXRlZCBieSB8KTwvcD48ZGl2IGNsYXNzPSJjZC1xLW9wdHMiPicrb3B0cy5tYXAoZnVuY3Rpb24obyl7cmV0dXJuICc8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImNkLWJ0biIgc3R5bGU9ImZvbnQtZmFtaWx5OnVpLW1vbm9zcGFjZSxNZW5sbyxDb25zb2xhcyxtb25vc3BhY2U7Zm9udC1zaXplOi44NXJlbSI+Jytlc2MobykrJzwvYnV0dG9uPid9KS5qb2luKCIiKSsnPC9kaXY+PGRpdiBjbGFzcz0iY2QtZmVlZGJhY2siIGhpZGRlbj48L2Rpdj48ZGl2IHN0eWxlPSJtYXJnaW4tdG9wOjEycHgiPjxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iY2QtYnRuIGNkLXByaW1hcnkgY2QtcHAtbmV4dCIgaGlkZGVuPicrKGk8UC5sZW5ndGgtMT8iTmV4dCBzbmlwcGV0IjoiU2VlIG15IHNjb3JlIikrJzwvYnV0dG9uPjwvZGl2Pic7CiAgJCQoIi5jZC1xLW9wdHMgYnV0dG9uIixib2R5KS5mb3JFYWNoKGZ1bmN0aW9uKGJ0LGspe2J0LmFkZEV2ZW50TGlzdGVuZXIoImNsaWNrIixmdW5jdGlvbigpe3ZhciBvaz1vcHRzW2tdPT09aXQuYW5zd2VyO2lmKG9rKXNjb3JlKys7JCQoIi5jZC1xLW9wdHMgYnV0dG9uIixib2R5KS5mb3JFYWNoKGZ1bmN0aW9uKHgsail7eC5kaXNhYmxlZD10cnVlO2lmKG9wdHNbal09PT1pdC5hbnN3ZXIpeC5jbGFzc0xpc3QuYWRkKCJjZC1yaWdodCIpO2Vsc2UgaWYoaj09PWspeC5jbGFzc0xpc3QuYWRkKCJjZC13cm9uZyIpfSk7CiAgIHZhciBmYj0kKCIuY2QtZmVlZGJhY2siLGJvZHkpO2ZiLmhpZGRlbj1mYWxzZTtmYi5jbGFzc05hbWU9ImNkLWZlZWRiYWNrICIrKG9rPyJjZC1vayI6ImNkLW5vIik7ZmIuaW5uZXJIVE1MPSI8Yj4iKyhvaz8iQ29ycmVjdC4iOiJOb3QgcXVpdGUuIE91dHB1dDogPGNvZGU+Iitlc2MoaXQuYW5zd2VyKSsiPC9jb2RlPiIpKyI8L2I+ICIrZXNjKGl0LndoeSk7JCgiLmNkLXBwLW5leHQiLGJvZHkpLmhpZGRlbj1mYWxzZX0pfSk7CiAgJCgiLmNkLXBwLW5leHQiLGJvZHkpLmFkZEV2ZW50TGlzdGVuZXIoImNsaWNrIixmdW5jdGlvbigpe2krKztpZihpPFAubGVuZ3RoKXNob3coKTtlbHNlIGRvbmUoKX0pfQogZnVuY3Rpb24gZG9uZSgpe2JvZHkuaW5uZXJIVE1MPSc8ZGl2IGNsYXNzPSJjZC1mZWVkYmFjayBjZC1vayI+PGI+WW91IHNjb3JlZCAnK3Njb3JlKycgb3V0IG9mICcrUC5sZW5ndGgrJy48L2I+ICcrKHNjb3JlPj0xMD8iRXhjZWxsZW50LiBOVUxMcyBhbmQgam9pbnMgaG9sZCBubyBzdXJwcmlzZXMgZm9yIHlvdS4iOnNjb3JlPj03PyJTb2xpZC4gUmV2aWV3IHRoZSBOVUxMIGFuZCBKT0lOIHF1ZXN0aW9ucyBhYm92ZSBmb3IgdGhlIG9uZXMgeW91IG1pc3NlZC4iOiJUaGVzZSBhcmUgdHJpY2t5IG9uIHB1cnBvc2UuIFJlYWQgdGhlIE5VTEwsIENPVU5UIGFuZCBKT0lOIHF1ZXN0aW9ucywgdGhlbiB0cnkgYWdhaW4uIikrJzwvZGl2PjxkaXYgc3R5bGU9Im1hcmdpbi10b3A6MTJweCI+PGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJjZC1idG4gY2QtcHAtYWdhaW4iPlBsYXkgYWdhaW48L2J1dHRvbj48L2Rpdj4nOyQoIi5jZC1wcC1hZ2FpbiIsYm9keSkuYWRkRXZlbnRMaXN0ZW5lcigiY2xpY2siLGZ1bmN0aW9uKCl7aT0wO3Njb3JlPTA7c2hvdygpfSl9CiAkKCIuY2QtcHAtc3RhcnQiLGJveCkuYWRkRXZlbnRMaXN0ZW5lcigiY2xpY2siLHNob3cpOwp9KTsKCi8qIGNvcHkgYnV0dG9ucyAqLwokJCgiLmNkLWNvcHkiKS5mb3JFYWNoKGZ1bmN0aW9uKGJ0KXtidC5hZGRFdmVudExpc3RlbmVyKCJjbGljayIsZnVuY3Rpb24oKXt2YXIgYm94PWJ0LmNsb3Nlc3QoIi5jZC1jb2RlYm94IiksY29kZT0kKCJwcmUgY29kZSIsYm94KTtmdW5jdGlvbiBvaygpe2J0LnRleHRDb250ZW50PSJDb3BpZWQiO3NldFRpbWVvdXQoZnVuY3Rpb24oKXtidC50ZXh0Q29udGVudD0iQ29weSJ9LDE1MDApfQogZnVuY3Rpb24gc2VsKCl7dmFyIHI9ZG9jdW1lbnQuY3JlYXRlUmFuZ2UoKTtyLnNlbGVjdE5vZGVDb250ZW50cyhjb2RlKTt2YXIgcz13aW5kb3cuZ2V0U2VsZWN0aW9uKCk7cy5yZW1vdmVBbGxSYW5nZXMoKTtzLmFkZFJhbmdlKHIpO2J0LnRleHRDb250ZW50PSJQcmVzcyBDdHJsK0MifQogaWYobmF2aWdhdG9yLmNsaXBib2FyZCYmbmF2aWdhdG9yLmNsaXBib2FyZC53cml0ZVRleHQpe25hdmlnYXRvci5jbGlwYm9hcmQud3JpdGVUZXh0KGNvZGUudGV4dENvbnRlbnQpLnRoZW4ob2ssc2VsKX1lbHNlIHNlbCgpfSl9KTsKCi8qIC0tLS0tLS0tLS0gbGl2ZSBTUUwgLS0tLS0tLS0tLSAqLwp2YXIgU1FMSlM9Imh0dHBzOi8vY2RuanMuY2xvdWRmbGFyZS5jb20vYWpheC9saWJzL3NxbC5qcy8xLjEwLjMvIixzcWxQPW51bGw7CmZ1bmN0aW9uIGxvYWRTUUwoKXtpZihzcWxQKXJldHVybiBzcWxQO3NxbFA9bmV3IFByb21pc2UoZnVuY3Rpb24ocmVzLHJlail7dmFyIHM9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgic2NyaXB0Iik7cy5zcmM9U1FMSlMrInNxbC13YXNtLmpzIjtzLm9ubG9hZD1mdW5jdGlvbigpe3dpbmRvdy5pbml0U3FsSnMoe2xvY2F0ZUZpbGU6ZnVuY3Rpb24oZil7cmV0dXJuIFNRTEpTK2Z9fSkudGhlbihyZXMsZnVuY3Rpb24oZSl7c3FsUD1udWxsO3JlaihlKX0pfTtzLm9uZXJyb3I9ZnVuY3Rpb24oKXtzcWxQPW51bGw7cmVqKG5ldyBFcnJvcigiQ291bGQgbm90IGxvYWQgdGhlIFNRTCBlbmdpbmUuIENoZWNrIHlvdXIgaW50ZXJuZXQgY29ubmVjdGlvbiBhbmQgdHJ5IGFnYWluLiIpKX07ZG9jdW1lbnQuaGVhZC5hcHBlbmRDaGlsZChzKX0pO3JldHVybiBzcWxQfQpmdW5jdGlvbiBmbXRWKHYpe2lmKHY9PT1udWxsfHx2PT09dW5kZWZpbmVkKXJldHVybiAiTlVMTCI7aWYodHlwZW9mIHY9PT0ibnVtYmVyIiYmIU51bWJlci5pc0ludGVnZXIodikpcmV0dXJuIFN0cmluZyhNYXRoLnJvdW5kKHYqMWU0KS8xZTQpO3JldHVybiBTdHJpbmcodil9CmZ1bmN0aW9uIHJ1blNRTChTUUwsc3FsKXt2YXIgZGI9bmV3IFNRTC5EYXRhYmFzZSgpLG91dD1bXTtkYi5ydW4od2luZG93LkNEX1NFRUQpO3RyeXt2YXIgaXQ9ZGIuaXRlcmF0ZVN0YXRlbWVudHMoc3FsKSxyO3doaWxlKCEocj1pdC5uZXh0KCkpLmRvbmUpe3ZhciBzdD1yLnZhbHVlLGNvbHM9c3QuZ2V0Q29sdW1uTmFtZXMoKSxyb3dzPVtdO3doaWxlKHN0LnN0ZXAoKSlyb3dzLnB1c2goc3QuZ2V0KCkpO2lmKGNvbHMubGVuZ3RoKW91dC5wdXNoKHtjb2xzOmNvbHMscm93czpyb3dzfSl9fWNhdGNoKGUpe291dC5wdXNoKHtlcnJvcjplLm1lc3NhZ2V9KX1kYi5jbG9zZSgpO3JldHVybiBvdXR9CmZ1bmN0aW9uIGVzYzIocyl7cmV0dXJuIFN0cmluZyhzKS5yZXBsYWNlKC8mL2csIiZhbXA7IikucmVwbGFjZSgvPC9nLCImbHQ7IikucmVwbGFjZSgvPi9nLCImZ3Q7Iil9CmZ1bmN0aW9uIHJlbmRlcihyZXMpe2lmKCFyZXMubGVuZ3RoKXJldHVybiAnPHAgY2xhc3M9ImNkLXNtYWxsIiBzdHlsZT0ibWFyZ2luOjAiPlN0YXRlbWVudCBleGVjdXRlZC4gTm8gcm93cyByZXR1cm5lZC48L3A+JzsKIHJldHVybiByZXMubWFwKGZ1bmN0aW9uKHIpe2lmKHIuZXJyb3IpcmV0dXJuICc8ZGl2IGNsYXNzPSJjZC1zcWwtZXJyIj5FcnJvcjogJytlc2MyKHIuZXJyb3IpKyc8L2Rpdj4nOwogIHJldHVybiAnPGRpdiBjbGFzcz0iY2QtdGJsLXdyYXAiPjx0YWJsZSBjbGFzcz0iY2QtdGJsIGNkLXJlcyI+PHRoZWFkPjx0cj4nK3IuY29scy5tYXAoZnVuY3Rpb24oYyl7cmV0dXJuICc8dGg+Jytlc2MyKGMpKyc8L3RoPid9KS5qb2luKCIiKSsnPC90cj48L3RoZWFkPjx0Ym9keT4nK3Iucm93cy5tYXAoZnVuY3Rpb24ocm93KXtyZXR1cm4gJzx0cj4nK3Jvdy5tYXAoZnVuY3Rpb24odil7cmV0dXJuICc8dGQnKyh2PT09bnVsbD8nIGNsYXNzPSJjZC1udWxsIic6JycpKyc+Jytlc2MyKGZtdFYodikpKyc8L3RkPid9KS5qb2luKCIiKSsnPC90cj4nfSkuam9pbigiIikrJzwvdGJvZHk+PC90YWJsZT48L2Rpdj48cCBjbGFzcz0iY2Qtc21hbGwiIHN0eWxlPSJtYXJnaW46NHB4IDAgMTBweCI+JytyLnJvd3MubGVuZ3RoKycgcm93Jysoci5yb3dzLmxlbmd0aD09PTE\/Jyc6J3MnKSsnPC9wPid9KS5qb2luKCIiKX0KZnVuY3Rpb24gcnVuSW50byhzcWwsdGFyZ2V0LGJ0bil7dmFyIGxhYmVsPWJ0bj9idG4udGV4dENvbnRlbnQ6IiI7aWYoYnRuKXtidG4uZGlzYWJsZWQ9dHJ1ZTtidG4udGV4dENvbnRlbnQ9IkxvYWRpbmfigKYifXRhcmdldC5oaWRkZW49ZmFsc2U7dGFyZ2V0LmlubmVySFRNTD0nPHAgY2xhc3M9ImNkLXNtYWxsIiBzdHlsZT0ibWFyZ2luOjAiPlN0YXJ0aW5nIHRoZSBTUUwgZW5naW5l4oCmPC9wPic7CiBsb2FkU1FMKCkudGhlbihmdW5jdGlvbihTUUwpe3ZhciB0MD1wZXJmb3JtYW5jZS5ub3coKSxyZXM9cnVuU1FMKFNRTCxzcWwpO3RhcmdldC5pbm5lckhUTUw9JzxkaXYgY2xhc3M9ImNkLWxpdmUtaGVhZCI+TGl2ZSByZXN1bHQgPHNwYW4+JytNYXRoLm1heCgxLE1hdGgucm91bmQocGVyZm9ybWFuY2Uubm93KCktdDApKSsnIG1zIMK3IGZyZXNoIGNvcHkgb2YgdGhlIHNhbXBsZSBkYXRhYmFzZTwvc3Bhbj48L2Rpdj4nK3JlbmRlcihyZXMpfSkKIC5jYXRjaChmdW5jdGlvbihlKXt0YXJnZXQuaW5uZXJIVE1MPSc8ZGl2IGNsYXNzPSJjZC1zcWwtZXJyIj4nK2VzYzIoZS5tZXNzYWdlKSsnPC9kaXY+J30pLnRoZW4oZnVuY3Rpb24oKXtpZihidG4pe2J0bi5kaXNhYmxlZD1mYWxzZTtidG4udGV4dENvbnRlbnQ9bGFiZWx9fSl9CiQkKCIuY2RhaS5jZC1jb2RlYm94W2RhdGEtcnVuXSIpLmZvckVhY2goZnVuY3Rpb24oYm94KXsKIHZhciBjb2RlPSQoInByZSBjb2RlIixib3gpLG9yaWc9Y29kZS50ZXh0Q29udGVudCxydW49JCgiLmNkLXJ1biIsYm94KSxlZD0kKCIuY2QtZWRpdCIsYm94KSxycz0kKCIuY2QtcmVzZXQiLGJveCksbGl2ZT0kKCIuY2QtbGl2ZSIsYm94KSxzdGF0PSQoIi5jZC1vdXRwIixib3gpOwogcnVuLmFkZEV2ZW50TGlzdGVuZXIoImNsaWNrIixmdW5jdGlvbigpe2lmKHN0YXQpc3RhdC5oaWRkZW49dHJ1ZTtydW5JbnRvKGNvZGUuaW5uZXJUZXh0LGxpdmUscnVuKX0pOwogZWQuYWRkRXZlbnRMaXN0ZW5lcigiY2xpY2siLGZ1bmN0aW9uKCl7dmFyIG9uPWNvZGUuZ2V0QXR0cmlidXRlKCJjb250ZW50ZWRpdGFibGUiKSE9PSJ0cnVlIjtjb2RlLnNldEF0dHJpYnV0ZSgiY29udGVudGVkaXRhYmxlIixvbj8idHJ1ZSI6ImZhbHNlIik7Y29kZS5zZXRBdHRyaWJ1dGUoInNwZWxsY2hlY2siLCJmYWxzZSIpO2JveC5jbGFzc0xpc3QudG9nZ2xlKCJjZC1lZGl0aW5nIixvbik7ZWQudGV4dENvbnRlbnQ9b24\/IkRvbmUiOiJFZGl0Ijtycy5oaWRkZW49ZmFsc2U7aWYob24pY29kZS5mb2N1cygpfSk7CiBycy5hZGRFdmVudExpc3RlbmVyKCJjbGljayIsZnVuY3Rpb24oKXtjb2RlLnRleHRDb250ZW50PW9yaWc7Y29kZS5zZXRBdHRyaWJ1dGUoImNvbnRlbnRlZGl0YWJsZSIsImZhbHNlIik7Ym94LmNsYXNzTGlzdC5yZW1vdmUoImNkLWVkaXRpbmciKTtlZC50ZXh0Q29udGVudD0iRWRpdCI7cnMuaGlkZGVuPXRydWU7bGl2ZS5oaWRkZW49dHJ1ZTtpZihzdGF0KXN0YXQuaGlkZGVuPWZhbHNlfSk7CiBjb2RlLmFkZEV2ZW50TGlzdGVuZXIoImtleWRvd24iLGZ1bmN0aW9uKGUpe2lmKChlLmN0cmxLZXl8fGUubWV0YUtleSkmJmUua2V5PT09IkVudGVyIil7ZS5wcmV2ZW50RGVmYXVsdCgpO3J1bi5jbGljaygpfX0pOwp9KTsKJCQoIi5jZGFpLmNkLXNxbC1wbGF5IikuZm9yRWFjaChmdW5jdGlvbihib3gpewogdmFyIHRhPSQoInRleHRhcmVhIixib3gpLG91dD0kKCIuY2QtcGxheS1vdXQiLGJveCksYnRuPSQoIi5jZC1wbGF5LXJ1biIsYm94KTsKIGJ0bi5hZGRFdmVudExpc3RlbmVyKCJjbGljayIsZnVuY3Rpb24oKXtydW5JbnRvKHRhLnZhbHVlLG91dCxidG4pfSk7CiB0YS5hZGRFdmVudExpc3RlbmVyKCJrZXlkb3duIixmdW5jdGlvbihlKXtpZigoZS5jdHJsS2V5fHxlLm1ldGFLZXkpJiZlLmtleT09PSJFbnRlciIpe2UucHJldmVudERlZmF1bHQoKTtidG4uY2xpY2soKX19KTsKICQkKCIuY2QtZXgiLGJveCkuZm9yRWFjaChmdW5jdGlvbihiKXtiLmFkZEV2ZW50TGlzdGVuZXIoImNsaWNrIixmdW5jdGlvbigpe3RhLnZhbHVlPWIuZGF0YXNldC5zcWw7YnRuLmNsaWNrKCl9KX0pOwogJCQoIi5jZC1wZWVrIixib3gpLmZvckVhY2goZnVuY3Rpb24oYil7Yi5hZGRFdmVudExpc3RlbmVyKCJjbGljayIsZnVuY3Rpb24oKXt0YS52YWx1ZT0iU0VMRUNUICogRlJPTSAiK2IuZGF0YXNldC50KyI7IjtidG4uY2xpY2soKX0pfSk7Cn0pOwp9KSgpOwo=\"><\/script>\n","protected":false},"excerpt":{"rendered":"<p>The 100 most asked SQL interview questions with answers and real query outputs, from freshers to experienced. Run every query live in your browser and download the free PDF.<\/p>\n","protected":false},"author":1,"featured_media":1175,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[50],"tags":[51],"class_list":["post-1176","post","type-post","status-publish","format-standard","has-post-thumbnail","category-sql","tag-sql"],"featured_image_src":"https:\/\/codeanddebug.in\/blog\/wp-content\/uploads\/2026\/10\/sql-interview-questions.jpg","author_info":{"display_name":"codeanddebug","author_link":"https:\/\/codeanddebug.in\/blog\/author\/codeanddebug\/"},"_links":{"self":[{"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/posts\/1176","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/comments?post=1176"}],"version-history":[{"count":1,"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/posts\/1176\/revisions"}],"predecessor-version":[{"id":1177,"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/posts\/1176\/revisions\/1177"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/media\/1175"}],"wp:attachment":[{"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/media?parent=1176"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/categories?post=1176"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/tags?post=1176"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}