SQL Part 1: SELECT, WHERE, JOIN, GROUP BY — data কোথায় থাকে

database থেকে data টেনে আনা (Series 03, Episode 06)

🟢 BEGINNER Series 03 — Data — AI-এর ভিত্তি Episode 06 / 09

📑 এই পর্বে যা যা আছে

🧩 ১. গল্প: Rahim-এর কাছে data নেই, আছে database access

Rahim এতদিন Pandas দিয়ে CSV file নিয়ে খেলছিল। কিন্তু প্রথম কাজের project-এ Boss একটা message দিলেন — "data-টা company-র PostgreSQL database-এ আছে, তোমাকে credential দিলাম, নিজে query করে বের করে নাও।"

Rahim: "আপা, আমাকে তো কেউ কোনো CSV দিল না! শুধু একটা database-এর host, username আর password দিল। এখন আমি data পাব কীভাবে?"

Nila: "স্বাগতম বাস্তব দুনিয়ায়! Company-তে ৯০% ক্ষেত্রে data থাকে database-এ, কোনো সাজানো CSV-তে না। সেই data টেনে আনার ভাষার নাম SQL — Structured Query Language। এটা AI Engineer-এর জন্য optional না, must-know। আজ আমরা এর core চারটা জিনিস শিখব: SELECT, WHERE, GROUP BY আর JOIN।"

২. সমস্যা: data সব সময় CSV হয়ে আসে না

Tutorial-এ data সবসময় সুন্দর একটা data.csv হিসেবে আসে। কিন্তু বাস্তবে data থাকে relational database-এ (PostgreSQL, MySQL) — অনেকগুলো table-এ ভাগ হয়ে, একে অপরের সাথে সম্পর্কিত অবস্থায়। যেমন একটা job portal-এ:

এই data থেকে "Dhaka-তে কোন industry-র company সবচেয়ে বেশি salary দেয়?" — এমন প্রশ্নের উত্তর পেতে হলে SQL লাগবেই। Pandas দিয়ে করার আগে data-টা database থেকে টেনে আনতে হবে।

🎯 ৩. কেন AI Engineer-এর SQL জানা লাগে

Must Know / Good to Know / Learn Later:
Must Know (চাকরির আগে): SELECT, WHERE, ORDER BY, GROUP BY, basic aggregation, INNER JOIN।
Good to Know: LEFT JOIN, HAVING, DISTINCT, subquery (পরের পর্ব)।
Learn Later (চাকরির পরে চললেও চলে): query optimization, stored procedure, database tuning।

🪜 ৪. তিন Level-এ SQL বোঝা

Level 1 — সহজ intuition

ভাবুন একটা বিশাল Excel sheet, লাখ লাখ row। আপনি একজন সহকারীকে বললেন — "শুধু Dhaka-র job গুলো দেখাও, আর salary বেশি থেকে কম সাজিয়ে দাও।" SQL হলো সেই সহকারীকে দেওয়া লিখিত নির্দেশ — কিন্তু এমন ভাষায় যা মেশিন নিখুঁতভাবে বোঝে।

Level 2 — technical ভাবে

SQL একটা declarative ভাষা — আপনি বলেন "কী চাই", "কীভাবে করব" সেটা database engine নিজে ঠিক করে। একটা SELECT query মূলত বলে: কোন column চাই, কোন table থেকে, কোন শর্তে (WHERE), কীভাবে group করব (GROUP BY), কীভাবে সাজাব (ORDER BY)।

Level 3 — engineer দৃষ্টিতে

Engineer রা SQL-কে দেখে data pipeline-এর প্রথম ধাপ হিসেবে। ভারী কাজ (filter, aggregate, join) database-এ সেরে নেওয়া হয় — কারণ database লাখ লাখ row নিয়ে optimize করা; তারপর ছোট, পরিষ্কার একটা result Python/Pandas-এ এনে ML-এ কাজে লাগানো হয়।

🗄️ ৫. আমাদের example database

এই পর্বে আমরা একটা সরল jobs table নিয়ে কাজ করব (একটা BD job portal-এর মতো):

CREATE TABLE jobs ( id SERIAL PRIMARY KEY, title TEXT, company_id INT, city TEXT, salary INT, experience INT ); -- কিছু sample data INSERT INTO jobs (title, company_id, city, salary, experience) VALUES ('Python Developer', 1, 'Dhaka', 45000, 1), ('ML Engineer', 2, 'Dhaka', 95000, 3), ('Data Analyst', 1, 'Chattogram', 40000, 1), ('Backend Engineer', 3, 'Dhaka', 70000, 2), ('ML Engineer', 2, 'Chattogram', 85000, 4), ('Data Scientist', 3, 'Dhaka', 120000, 5); CREATE TABLE companies ( id INT PRIMARY KEY, name TEXT, industry TEXT ); INSERT INTO companies (id, name, industry) VALUES (1, 'TechShop BD', 'E-commerce'), (2, 'DataFirst Ltd', 'AI/ML'), (3, 'FinPay', 'Fintech');

কেন PostgreSQL? বাংলাদেশে ও বিশ্বজুড়ে এটি সবচেয়ে জনপ্রিয় open-source relational database, আর পরের সিরিজে (Series 08) আমরা এর pgvector extension দিয়ে vector search-ও করব — তাই এখন থেকেই এতে অভ্যস্ত হওয়া ভালো।

🔍 ৬. SELECT ও WHERE: প্রথম query

SELECT বলে কোন column চাই, FROM বলে কোন table, WHERE বলে কোন শর্তে row বাছব।

-- সব column, সব row SELECT * FROM jobs; -- শুধু কিছু column SELECT title, salary, city FROM jobs; -- WHERE: শর্ত দিয়ে row বাছাই SELECT title, salary FROM jobs WHERE city = 'Dhaka'; -- একাধিক শর্ত (AND / OR) SELECT title, salary FROM jobs WHERE city = 'Dhaka' AND salary > 60000; -- range ও pattern SELECT title FROM jobs WHERE salary BETWEEN 40000 AND 90000; SELECT title FROM jobs WHERE title LIKE '%Engineer%'; -- title-এ "Engineer" আছে এমন
খেয়াল করুন: SQL-এ সমান তুলনায় একটা = ব্যবহার হয় (Python-এর মতো == না)। আর text-এর চারপাশে single quote 'Dhaka', double quote না।

📑 ৭. ORDER BY, LIMIT, DISTINCT

-- salary বেশি থেকে কম সাজানো SELECT title, salary FROM jobs ORDER BY salary DESC; -- top 3 highest-paying job SELECT title, salary FROM jobs ORDER BY salary DESC LIMIT 3; -- unique শহরের তালিকা (duplicate বাদ) SELECT DISTINCT city FROM jobs;

DESC = descending (বড় থেকে ছোট), ASC = ascending (ছোট থেকে বড়, default)। LIMIT বড় table-এ খুব দরকারি — লাখ row-এর জায়গায় শুধু কয়েকটা দেখতে।

৮. Aggregation: COUNT, AVG, SUM, MIN, MAX

Aggregation function গুলো অনেক row-কে একটা সংখ্যায় নামিয়ে আনে:

-- মোট কতগুলো job আছে? SELECT COUNT(*) FROM jobs; -- সব job-এর গড় salary SELECT AVG(salary) FROM jobs; -- সর্বোচ্চ ও সর্বনিম্ন salary SELECT MAX(salary), MIN(salary) FROM jobs; -- Dhaka-র job-এর গড় salary SELECT AVG(salary) FROM jobs WHERE city = 'Dhaka'; -- পড়ার সুবিধায় column-এর নাম (alias) দেওয়া SELECT AVG(salary) AS avg_salary, COUNT(*) AS total_jobs FROM jobs WHERE city = 'Dhaka';
Pandas-এর সাথে মিল: SQL-এর AVG(salary) = Pandas-এর df["salary"].mean()। একই ধারণা, দুই জায়গায় দুই ভাষা।

🧮 ৯. GROUP BY: প্রতিটা group-এর হিসাব

"প্রতিটা শহরে গড় salary কত?" — এখানে সব row-এর একটা গড় না, বরং প্রতিটা শহরের আলাদা গড় চাই। এটাই GROUP BY। ঠিক Pandas-এর groupby-এর মতো।

-- প্রতিটা শহরে গড় salary ও job সংখ্যা SELECT city, AVG(salary) AS avg_salary, COUNT(*) AS total_jobs FROM jobs GROUP BY city; -- প্রতিটা title-এ কতজন SELECT title, COUNT(*) AS cnt FROM jobs GROUP BY title ORDER BY cnt DESC;
GROUP BY city যেভাবে কাজ করে: সব row group ভাগ AVG(salary) Dhaka 45000 Dhaka: 45k,95k,70k,120k -> 82500 Dhaka 95000 => Chatto: 40k,85k -> 62500 Chatto 40000 Dhaka 70000 (প্রতিটা group => একটা row) Chatto 85000 Dhaka 120000
নিয়ম: SELECT-এ যে column আছে অথচ aggregation function-এর ভেতরে নেই, সেটা অবশ্যই GROUP BY-তে থাকতে হবে। যেমন উপরে city GROUP BY-তে আছে, কিন্তু salary AVG()-এর ভেতরে।

🚦 ১০. HAVING: group-এর উপর filter

WHERE দিয়ে আমরা row filter করি, কিন্তু group করার পরে group-এর উপর filter করতে হলে HAVING লাগে।

-- শুধু সেই শহর যেখানে গড় salary 70000-এর বেশি SELECT city, AVG(salary) AS avg_salary FROM jobs GROUP BY city HAVING AVG(salary) > 70000; -- ভুল: WHERE দিয়ে aggregate filter করা যায় না -- SELECT city FROM jobs WHERE AVG(salary) > 70000 -- ERROR!
মনে রাখার সহজ উপায়: WHERE কাজ করে group করার আগে (individual row-এ), HAVING কাজ করে group করার পরে (group-এর aggregate value-তে)।

🔗 ১১. JOIN: দুটো table জোড়া

Job-এর company-র নাম চাই? কিন্তু jobs table-এ শুধু company_id আছে, নাম নেই। নাম আছে companies table-এ। দুটো table জোড়া লাগবে — এটাই JOIN, relational database-এর হৃদয়।

-- INNER JOIN: দুই table-এ মিল আছে এমন row SELECT jobs.title, jobs.salary, companies.name, companies.industry FROM jobs INNER JOIN companies ON jobs.company_id = companies.id; -- alias দিয়ে সংক্ষিপ্ত করা SELECT j.title, j.salary, c.name AS company, c.industry FROM jobs AS j JOIN companies AS c ON j.company_id = c.id WHERE c.industry = 'AI/ML'; -- JOIN + GROUP BY একসাথে: -- প্রতিটা industry-তে গড় salary SELECT c.industry, AVG(j.salary) AS avg_salary FROM jobs j JOIN companies c ON j.company_id = c.id GROUP BY c.industry ORDER BY avg_salary DESC;
INNER JOIN jobs ON companies: jobs companies company_id=2 ─────┐ id=2 DataFirst (AI/ML) └─mel─> মিলে গেলে একসাথে এক row company_id=1 ─────────> id=1 TechShop (E-commerce) মিল নেই এমন row INNER JOIN-এ বাদ পড়ে। LEFT JOIN হলে বাম table-এর সব row থাকে (পরের পর্বে বিস্তারিত)।

⚙️ ১২. Query চালানোর ক্রম (কীভাবে SQL চিন্তা করে)

আমরা লিখি SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY — কিন্তু database আসলে এই ক্রমে চালায় না। বোঝার জন্য এই logical order-টা মনে রাখুন:

১. FROM -- কোন table থেকে ২. WHERE -- row filter (group করার আগে) ৩. GROUP BY -- row গুলো group করা ৪. HAVING -- group filter (aggregate-এর উপর) ৫. SELECT -- কোন column/হিসাব দেখাব ৬. ORDER BY -- ফল সাজানো ৭. LIMIT -- কতগুলো row রাখব

এই ক্রমটা মাথায় থাকলে জটিল query-তেও কেন WHERE aggregate filter করতে পারে না (তখনো group হয়নি) — সেটা পরিষ্কার হয়ে যায়।

🇧🇩 ১৩. বাস্তব উদাহরণ: Bangladesh job database

ধরুন Daraz বা Bikroy-এর মতো একটা platform-এ hiring data আছে। একজন AI Engineer হয়তো এমন query চালাবে একটা salary-prediction model-এর জন্য data প্রস্তুত করতে:

-- প্রতিটা শহর ও industry-তে: গড় salary, -- মোট job, সর্বোচ্চ salary — শুধু সেই combination -- যেখানে অন্তত ২টা job আছে (নাহলে গড় নির্ভরযোগ্য না) SELECT j.city, c.industry, COUNT(*) AS total_jobs, AVG(j.salary) AS avg_salary, MAX(j.salary) AS max_salary FROM jobs j JOIN companies c ON j.company_id = c.id WHERE j.salary IS NOT NULL GROUP BY j.city, c.industry HAVING COUNT(*) >= 2 ORDER BY avg_salary DESC;

এই একটা query-তেই আছে JOIN, WHERE, GROUP BY, HAVING, aggregation আর ORDER BY — অর্থাৎ আজকের পুরো পর্বের প্রয়োগ।

👷 ১৪. একজন AI Engineer-এর দৃষ্টিতে

AI Engineer রা সাধারণত Python-এ SQL চালায় — database থেকে data টেনে সরাসরি Pandas DataFrame-এ আনে:

import pandas as pd from sqlalchemy import create_engine # PostgreSQL-এ connect engine = create_engine( "postgresql://user:password@localhost:5432/jobsdb" ) query = """ SELECT city, AVG(salary) AS avg_salary, COUNT(*) AS cnt FROM jobs GROUP BY city ORDER BY avg_salary DESC """ # SQL result সরাসরি DataFrame-এ df = pd.read_sql(query, engine) print(df)
Golden rule: ভারী filtering ও aggregation SQL-এ (database-এ) করো, তারপর ছোট পরিষ্কার result Pandas-এ এনে ML-এর কাজ করো। লাখ লাখ row কখনো অকারণে Python-এ টেনে এনো না — মেমরি শেষ হয়ে যাবে, ধীরও হবে।

💼 ১৫. Boss Question

Boss: "Pandas তো শিখেছ, তাহলে SQL আবার কেন? চাকরিতে এটা কোথায় লাগবে?"

উত্তর: লাগবে কারণ company-র আসল data থাকে database-এ, কোনো ready CSV-তে না। একটা recommendation model বা churn model বানাতে আগে সেই data টানতে হবে — সেটা SQL ছাড়া হয় না। তাছাড়া data যখন কোটি row, তখন পুরোটা Python-এ টানা অসম্ভব; SQL দিয়ে database-এই দরকারি অংশটুকু filter/aggregate করে আনতে হয় — এতে সময় ও খরচ দুটোই বাঁচে। তাই SQL শুধু "জানলে ভালো" না, এটা প্রায় প্রতিটা AI/ML JD-র বাধ্যতামূলক অংশ।

🔎 ১৬. Job Requirement Decoder

Job description-এ প্রায়ই দেখবেন:

"Proficiency in SQL for data extraction and analysis."
প্রশ্নউত্তর
এর মানে কী?আপনি database থেকে নিজে query লিখে data বের করতে ও বিশ্লেষণ করতে পারেন।
কোম্পানি কেন চায়?ML-এর training data ও business report প্রায় সবসময় SQL query দিয়েই আসে।
কোন সমস্যা সমাধান করে?data অন্যের হাতে বসে থাকার নির্ভরতা কমায় — আপনি নিজেই data নিতে পারেন।
Junior-এর কী জানা লাগে?SELECT, WHERE, ORDER BY, GROUP BY, aggregation, INNER JOIN — এই পর্বের সবকিছু।
এখনই কী master লাগে না?query performance tuning, execution plan, indexing internals — এখন না।
GitHub-এ কীভাবে দেখাবেন?একটা project-এ .sql file বা read_sql দিয়ে data-loading step রাখুন; README-তে schema diagram দিন।
Interview-তে কী জিজ্ঞেস করতে পারে?"WHERE vs HAVING?", "INNER vs LEFT JOIN?", "এই দুই table থেকে প্রতিটা শহরে গড় salary বের করুন।"

⚠️ ১৭. সাধারণ ভুল ধারণা

ভুল ১: সমান তুলনায় == লেখা। → ঠিক: SQL-এ single = (WHERE city = 'Dhaka')।

ভুল ২: aggregate filter করতে WHERE AVG(salary) > 70000 লেখা। → ঠিক: group-এর aggregate filter করতে HAVING লাগে।

ভুল ৩: GROUP BY-তে column বাদ দেওয়া। → ঠিক: SELECT-এ non-aggregate column অবশ্যই GROUP BY-তে থাকতে হবে।

ভুল ৪: NULL-কে সাধারণ value ভাবা। → ঠিক: = NULL কাজ করে না; IS NULL / IS NOT NULL ব্যবহার করুন।

ভুল ৫: বড় table-এ SELECT * চালানো। → ঠিক: শুধু দরকারি column নিন, আর test-এর সময় LIMIT দিন।

🎤 ১৮. Interview Prep

প্রশ্ন ১: WHERE আর HAVING-এর পার্থক্য কী?
উত্তর: WHERE row filter করে group করার আগে; HAVING group-এর aggregate value filter করে group করার পরে।

প্রশ্ন ২: INNER JOIN আর LEFT JOIN-এর পার্থক্য?
উত্তর: INNER JOIN দুই table-এ মিল থাকা row দেয়; LEFT JOIN বাম table-এর সব row রাখে, ডানে মিল না পেলে NULL বসায়।

প্রশ্ন ৩: SQL query-র logical execution order কী?
উত্তর: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT।

প্রশ্ন ৪: COUNT(*) আর COUNT(column)-এর পার্থক্য?
উত্তর: COUNT(*) সব row গোনে; COUNT(column) সেই column-এ NULL নয় এমন row গোনে।

✍️ ১৯. হাতে-কলমে (Mini Exercise)

উপরের jobscompanies table ব্যবহার করে নিচের query গুলো নিজে লিখুন:

১. শুধু Dhaka-র job গুলোর title ও salary, salary বেশি থেকে কম সাজিয়ে।
২. প্রতিটা শহরে মোট কতগুলো job আছে।
৩. প্রতিটা industry-তে গড় salary (JOIN লাগবে)।
৪. শুধু সেই title যেগুলো একাধিকবার আছে (HAVING COUNT(*) > 1)।
৫. সবচেয়ে বেশি salary দেওয়া top ৩টি job ও তাদের company-র নাম।

(চেষ্টা করার পরেই কেবল উত্তর মেলান — নিজে লিখলেই আসল শেখা হয়।)

🚀 ২০. Project Connection

আমাদের flagship "Bangladesh Tech Career Assistant" এখন V2 পর্যায়ে (data analysis)। এতদিন CSV থেকে data নিচ্ছিলাম; কিন্তু বাস্তব version-এ job data একটা PostgreSQL database-এ রাখব।

আজকের SQL দিয়ে আমরা flagship-এর জন্য এমন query লিখব — "প্রতিটা শহর ও role-এ গড় salary", "কোন skill সবচেয়ে বেশি চাওয়া হয়" — যা সরাসরি Project P1 (Bangladesh Job Market Data Analyzer)-এ কাজে লাগবে। পরের পর্বে window function দিয়ে এগুলো আরও শক্তিশালী করব।

📌 ২১. সারসংক্ষেপ

এই পর্বে আমরা শিখলাম:

✓ কেন data database-এ থাকে আর AI Engineer-এর SQL কেন must-know
SELECT / WHERE দিয়ে column ও row বাছাই
ORDER BY, LIMIT, DISTINCT দিয়ে সাজানো ও সীমিত করা
COUNT, AVG, SUM, MIN, MAX aggregation
GROUP BY দিয়ে প্রতিটা group-এর হিসাব, আর HAVING দিয়ে group filter
JOIN দিয়ে দুটো table জোড়া
✓ SQL-এর logical execution order আর Python/Pandas-এ result টেনে আনা
✓ Golden rule — ভারী কাজ database-এ, পরিষ্কার result Python-এ

➡️ ২২. পরবর্তী পর্বে কী শিখব

পরবর্তী Episode (S03E07): "SQL Part 2 — subquery, window function, index"।

Basic query তো হলো, কিন্তু "প্রতিটা শহরের মধ্যে top ৩ salary" বা "running total" — এসব জায়গায় junior রা আটকায়। পরের পর্বে আমরা subquery, শক্তিশালী window function (RANK, ROW_NUMBER) আর index কী ও কেন দরকার — সেই analytical SQL শিখব।
© 2025 Sheikh Thanbir Alam. All Rights Reserved. thanbirtamim.github.io
এই লেখা মূল লেখকের সম্পত্তি — লিখিত অনুমতি ছাড়া কপি করে অন্য কোনো ওয়েবসাইট, ব্লগ, বই বা প্ল্যাটফর্মে প্রকাশ/বিতরণ করা কঠোরভাবে নিষিদ্ধ। Content may not be copied or republished without permission.