feat: full 49-block admission catalog + winning-block label in top-100 query

- admission-blocks.js: expand from 8 core blocks to all 49 official 2017
  blocks (A00-A11, B00-B08, C00-C20, D01-D15) the DB schema can support.
  Detail card now shows every qualifying block, sorted best-first
- custom-query: rewrite "Top 100 Long An" preset using UNION ALL +
  ROW_NUMBER() OVER PARTITION BY so we can label each row with the
  winning block code, not just the score
This commit is contained in:
2026-04-14 23:17:58 +07:00
parent 655d8f8cfc
commit da4c017e96
2 changed files with 115 additions and 72 deletions
+63 -64
View File
@@ -52,71 +52,70 @@ WHERE so_bao_danh LIKE '49%'
ORDER BY tong_khoi_a DESC LIMIT 10`,
},
{
// Per-student MAX across 49 official 2017 blocks (A00-A11, B00-B08,
// C00-C20, D01-D15) restricted to subjects in our DB. SQLite's
// MAX(x,y,...) scalar returns NULL if ANY arg is NULL (not just all),
// so every block is wrapped in COALESCE(..., -1). NULLIF(..., -1)
// then restores NULL for students whose data yields no valid block.
// Top 100 Long An students by their best of 49 official 2017
// admission blocks. Each (student, block) pair is materialised via
// UNION ALL; ROW_NUMBER picks each student's #1 block; the outer
// SELECT ranks across students. Result includes the winning block
// code so the user sees which combination produced the score.
label: "Top 100 điểm khối cao nhất - Long An",
sql: `SELECT
so_bao_danh,
ho_ten,
ngay_sinh,
ROUND(NULLIF(MAX(
COALESCE(toan+vat_ly+hoa_hoc, -1), -- A00
COALESCE(toan+vat_ly+tieng_anh, -1), -- A01
COALESCE(toan+vat_ly+sinh_hoc, -1), -- A02
COALESCE(toan+vat_ly+lich_su, -1), -- A03
COALESCE(toan+vat_ly+dia_ly, -1), -- A04
COALESCE(toan+hoa_hoc+lich_su, -1), -- A05
COALESCE(toan+hoa_hoc+dia_ly, -1), -- A06
COALESCE(toan+lich_su+dia_ly, -1), -- A07
COALESCE(toan+lich_su+gdcd, -1), -- A08
COALESCE(toan+dia_ly+gdcd, -1), -- A09
COALESCE(toan+vat_ly+gdcd, -1), -- A10
COALESCE(toan+hoa_hoc+gdcd, -1), -- A11
COALESCE(toan+hoa_hoc+sinh_hoc, -1), -- B00
COALESCE(toan+sinh_hoc+lich_su, -1), -- B01
COALESCE(toan+sinh_hoc+dia_ly, -1), -- B02
COALESCE(toan+sinh_hoc+ngu_van, -1), -- B03
COALESCE(toan+sinh_hoc+gdcd, -1), -- B04
COALESCE(toan+sinh_hoc+tieng_anh, -1), -- B08
COALESCE(ngu_van+lich_su+dia_ly, -1), -- C00
COALESCE(ngu_van+toan+vat_ly, -1), -- C01
COALESCE(ngu_van+toan+hoa_hoc, -1), -- C02
COALESCE(ngu_van+toan+lich_su, -1), -- C03
COALESCE(ngu_van+toan+dia_ly, -1), -- C04
COALESCE(ngu_van+vat_ly+hoa_hoc, -1), -- C05
COALESCE(ngu_van+vat_ly+sinh_hoc, -1), -- C06
COALESCE(ngu_van+vat_ly+lich_su, -1), -- C07
COALESCE(ngu_van+hoa_hoc+sinh_hoc, -1), -- C08
COALESCE(ngu_van+vat_ly+dia_ly, -1), -- C09
COALESCE(ngu_van+hoa_hoc+lich_su, -1), -- C10
COALESCE(ngu_van+sinh_hoc+lich_su, -1), -- C12
COALESCE(ngu_van+sinh_hoc+dia_ly, -1), -- C13
COALESCE(ngu_van+toan+gdcd, -1), -- C14
COALESCE(ngu_van+vat_ly+gdcd, -1), -- C16
COALESCE(ngu_van+hoa_hoc+gdcd, -1), -- C17
COALESCE(ngu_van+lich_su+gdcd, -1), -- C19
COALESCE(ngu_van+dia_ly+gdcd, -1), -- C20
COALESCE(toan+ngu_van+tieng_anh, -1), -- D01
COALESCE(toan+ngu_van+tieng_nga, -1), -- D02
COALESCE(toan+ngu_van+tieng_phap, -1), -- D03
COALESCE(toan+ngu_van+tieng_trung, -1), -- D04
COALESCE(toan+hoa_hoc+tieng_anh, -1), -- D07
COALESCE(toan+sinh_hoc+tieng_anh, -1), -- D08
COALESCE(toan+lich_su+tieng_anh, -1), -- D09
COALESCE(toan+dia_ly+tieng_anh, -1), -- D10
COALESCE(ngu_van+vat_ly+tieng_anh, -1), -- D11
COALESCE(ngu_van+hoa_hoc+tieng_anh, -1), -- D12
COALESCE(ngu_van+sinh_hoc+tieng_anh, -1), -- D13
COALESCE(ngu_van+lich_su+tieng_anh, -1), -- D14
COALESCE(ngu_van+dia_ly+tieng_anh, -1) -- D15
), -1), 2) AS diem_khoi_cao_nhat
FROM student
WHERE so_bao_danh LIKE '49%'
ORDER BY diem_khoi_cao_nhat IS NULL, diem_khoi_cao_nhat DESC
LIMIT 100`,
sql: `WITH per_block AS (
SELECT so_bao_danh, ho_ten, ngay_sinh, 'A00' k, toan+vat_ly+hoa_hoc s FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'A01', toan+vat_ly+tieng_anh FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'A02', toan+vat_ly+sinh_hoc FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'A03', toan+vat_ly+lich_su FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'A04', toan+vat_ly+dia_ly FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'A05', toan+hoa_hoc+lich_su FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'A06', toan+hoa_hoc+dia_ly FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'A07', toan+lich_su+dia_ly FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'A08', toan+lich_su+gdcd FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'A09', toan+dia_ly+gdcd FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'A10', toan+vat_ly+gdcd FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'A11', toan+hoa_hoc+gdcd FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'B00', toan+hoa_hoc+sinh_hoc FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'B01', toan+sinh_hoc+lich_su FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'B02', toan+sinh_hoc+dia_ly FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'B03', toan+sinh_hoc+ngu_van FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'B04', toan+sinh_hoc+gdcd FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'B08', toan+sinh_hoc+tieng_anh FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'C00', ngu_van+lich_su+dia_ly FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'C01', ngu_van+toan+vat_ly FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'C02', ngu_van+toan+hoa_hoc FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'C03', ngu_van+toan+lich_su FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'C04', ngu_van+toan+dia_ly FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'C05', ngu_van+vat_ly+hoa_hoc FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'C06', ngu_van+vat_ly+sinh_hoc FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'C07', ngu_van+vat_ly+lich_su FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'C08', ngu_van+hoa_hoc+sinh_hoc FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'C09', ngu_van+vat_ly+dia_ly FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'C10', ngu_van+hoa_hoc+lich_su FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'C12', ngu_van+sinh_hoc+lich_su FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'C13', ngu_van+sinh_hoc+dia_ly FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'C14', ngu_van+toan+gdcd FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'C16', ngu_van+vat_ly+gdcd FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'C17', ngu_van+hoa_hoc+gdcd FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'C19', ngu_van+lich_su+gdcd FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'C20', ngu_van+dia_ly+gdcd FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'D01', toan+ngu_van+tieng_anh FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'D02', toan+ngu_van+tieng_nga FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'D03', toan+ngu_van+tieng_phap FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'D04', toan+ngu_van+tieng_trung FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'D07', toan+hoa_hoc+tieng_anh FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'D08', toan+sinh_hoc+tieng_anh FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'D09', toan+lich_su+tieng_anh FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'D10', toan+dia_ly+tieng_anh FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'D11', ngu_van+vat_ly+tieng_anh FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'D12', ngu_van+hoa_hoc+tieng_anh FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'D13', ngu_van+sinh_hoc+tieng_anh FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'D14', ngu_van+lich_su+tieng_anh FROM student WHERE so_bao_danh LIKE '49%'
UNION ALL SELECT so_bao_danh, ho_ten, ngay_sinh, 'D15', ngu_van+dia_ly+tieng_anh FROM student WHERE so_bao_danh LIKE '49%'
),
ranked AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY so_bao_danh ORDER BY s DESC, k) rn
FROM per_block WHERE s IS NOT NULL
)
SELECT so_bao_danh, ho_ten, ngay_sinh, k AS khoi, ROUND(s, 2) AS diem
FROM ranked WHERE rn = 1
ORDER BY diem DESC LIMIT 100`,
},
],
},
+52 -8
View File
@@ -2,15 +2,59 @@
// Each block is the sum of 3 subjects; we only compute a block when ALL three
// subject scores exist for the student.
// Full 2017 admission-block list (Circular 03/2017/TT-BGDĐT) restricted to
// the 12 subjects available in our DB. Blocks needing Tiếng Đức / Nhật are
// excluded — neither language appears in any source file.
export const ADMISSION_BLOCKS = [
{ code: "A", subjects: ["toan", "vat_ly", "hoa_hoc"], label: "Toán + Lý + Hóa" },
{ code: "A1", subjects: ["toan", "vat_ly", "tieng_anh"], label: "Toán + Lý + Anh" },
{ code: "B", subjects: ["toan", "hoa_hoc", "sinh_hoc"], label: "Toán + Hóa + Sinh" },
{ code: "C", subjects: ["ngu_van", "lich_su", "dia_ly"], label: "n + Sử + Địa" },
{ code: "D1", subjects: ["toan", "ngu_van", "tieng_anh"], label: "Toán + Văn + Anh" },
{ code: "D2", subjects: ["toan", "ngu_van", "tieng_nga"], label: "Toán + Văn + Nga" },
{ code: "D3", subjects: ["toan", "ngu_van", "tieng_phap"], label: "Toán + Văn + Pháp" },
{ code: "D4", subjects: ["toan", "ngu_van", "tieng_trung"], label: "Toán + Văn + Trung" },
{ code: "A00", subjects: ["toan", "vat_ly", "hoa_hoc"], label: "Toán + Lý + Hóa" },
{ code: "A01", subjects: ["toan", "vat_ly", "tieng_anh"], label: "Toán + Lý + Anh" },
{ code: "A02", subjects: ["toan", "vat_ly", "sinh_hoc"], label: "Toán + + Sinh" },
{ code: "A03", subjects: ["toan", "vat_ly", "lich_su"], label: "Toán + + Sử" },
{ code: "A04", subjects: ["toan", "vat_ly", "dia_ly"], label: "Toán + Lý + Địa" },
{ code: "A05", subjects: ["toan", "hoa_hoc", "lich_su"], label: "Toán + Hóa + Sử" },
{ code: "A06", subjects: ["toan", "hoa_hoc", "dia_ly"], label: "Toán + Hóa + Địa" },
{ code: "A07", subjects: ["toan", "lich_su", "dia_ly"], label: "Toán + Sử + Địa" },
{ code: "A08", subjects: ["toan", "lich_su", "gdcd"], label: "Toán + Sử + GDCD" },
{ code: "A09", subjects: ["toan", "dia_ly", "gdcd"], label: "Toán + Địa + GDCD" },
{ code: "A10", subjects: ["toan", "vat_ly", "gdcd"], label: "Toán + Lý + GDCD" },
{ code: "A11", subjects: ["toan", "hoa_hoc", "gdcd"], label: "Toán + Hóa + GDCD" },
{ code: "B00", subjects: ["toan", "hoa_hoc", "sinh_hoc"], label: "Toán + Hóa + Sinh" },
{ code: "B01", subjects: ["toan", "sinh_hoc", "lich_su"], label: "Toán + Sinh + Sử" },
{ code: "B02", subjects: ["toan", "sinh_hoc", "dia_ly"], label: "Toán + Sinh + Địa" },
{ code: "B03", subjects: ["toan", "sinh_hoc", "ngu_van"], label: "Toán + Sinh + Văn" },
{ code: "B04", subjects: ["toan", "sinh_hoc", "gdcd"], label: "Toán + Sinh + GDCD" },
{ code: "B08", subjects: ["toan", "sinh_hoc", "tieng_anh"], label: "Toán + Sinh + Anh" },
{ code: "C00", subjects: ["ngu_van", "lich_su", "dia_ly"], label: "Văn + Sử + Địa" },
{ code: "C01", subjects: ["ngu_van", "toan", "vat_ly"], label: "Văn + Toán + Lý" },
{ code: "C02", subjects: ["ngu_van", "toan", "hoa_hoc"], label: "Văn + Toán + Hóa" },
{ code: "C03", subjects: ["ngu_van", "toan", "lich_su"], label: "Văn + Toán + Sử" },
{ code: "C04", subjects: ["ngu_van", "toan", "dia_ly"], label: "Văn + Toán + Địa" },
{ code: "C05", subjects: ["ngu_van", "vat_ly", "hoa_hoc"], label: "Văn + Lý + Hóa" },
{ code: "C06", subjects: ["ngu_van", "vat_ly", "sinh_hoc"], label: "Văn + Lý + Sinh" },
{ code: "C07", subjects: ["ngu_van", "vat_ly", "lich_su"], label: "Văn + Lý + Sử" },
{ code: "C08", subjects: ["ngu_van", "hoa_hoc", "sinh_hoc"], label: "Văn + Hóa + Sinh" },
{ code: "C09", subjects: ["ngu_van", "vat_ly", "dia_ly"], label: "Văn + Lý + Địa" },
{ code: "C10", subjects: ["ngu_van", "hoa_hoc", "lich_su"], label: "Văn + Hóa + Sử" },
{ code: "C12", subjects: ["ngu_van", "sinh_hoc", "lich_su"], label: "Văn + Sinh + Sử" },
{ code: "C13", subjects: ["ngu_van", "sinh_hoc", "dia_ly"], label: "Văn + Sinh + Địa" },
{ code: "C14", subjects: ["ngu_van", "toan", "gdcd"], label: "Văn + Toán + GDCD" },
{ code: "C16", subjects: ["ngu_van", "vat_ly", "gdcd"], label: "Văn + Lý + GDCD" },
{ code: "C17", subjects: ["ngu_van", "hoa_hoc", "gdcd"], label: "Văn + Hóa + GDCD" },
{ code: "C19", subjects: ["ngu_van", "lich_su", "gdcd"], label: "Văn + Sử + GDCD" },
{ code: "C20", subjects: ["ngu_van", "dia_ly", "gdcd"], label: "Văn + Địa + GDCD" },
{ code: "D01", subjects: ["toan", "ngu_van", "tieng_anh"], label: "Toán + Văn + Anh" },
{ code: "D02", subjects: ["toan", "ngu_van", "tieng_nga"], label: "Toán + Văn + Nga" },
{ code: "D03", subjects: ["toan", "ngu_van", "tieng_phap"], label: "Toán + Văn + Pháp" },
{ code: "D04", subjects: ["toan", "ngu_van", "tieng_trung"], label: "Toán + Văn + Trung" },
{ code: "D07", subjects: ["toan", "hoa_hoc", "tieng_anh"], label: "Toán + Hóa + Anh" },
{ code: "D08", subjects: ["toan", "sinh_hoc", "tieng_anh"], label: "Toán + Sinh + Anh" },
{ code: "D09", subjects: ["toan", "lich_su", "tieng_anh"], label: "Toán + Sử + Anh" },
{ code: "D10", subjects: ["toan", "dia_ly", "tieng_anh"], label: "Toán + Địa + Anh" },
{ code: "D11", subjects: ["ngu_van", "vat_ly", "tieng_anh"], label: "Văn + Lý + Anh" },
{ code: "D12", subjects: ["ngu_van", "hoa_hoc", "tieng_anh"], label: "Văn + Hóa + Anh" },
{ code: "D13", subjects: ["ngu_van", "sinh_hoc", "tieng_anh"], label: "Văn + Sinh + Anh" },
{ code: "D14", subjects: ["ngu_van", "lich_su", "tieng_anh"], label: "Văn + Sử + Anh" },
{ code: "D15", subjects: ["ngu_van", "dia_ly", "tieng_anh"], label: "Văn + Địa + Anh" },
];
// Returns { code, label, total, parts:[{key,score}] } for every block where