SQL बेसिक्स: SELECT, WHERE और ORDER BY
SQL (Structured Query Language) relational databases से query करने की standard language है। SELECT statement कुछ भी बदले बिना rows पढ़ता है: यह CRUD का read है। FROM बताता है कि किस table से पढ़ना है, और ज़्यादातर काम तीन clauses करते हैं: SELECT columns बताता है, WHERE condition से match होने वाली rows रखता है और ORDER BY result को sort करता है।
उदाहरण के लिए, SELECT order_id, status FROM orders WHERE customer_id = 207 ORDER BY created_at DESC; customer 207 के orders सबसे नए पहले दिखाता है। Testers ऐसी queries से देखते हैं कि application ने असल में क्या store किया, और expected results निकालते हैं।
यह क्यों ज़रूरी है
Screen और API data तब दिखाते हैं जब application उसे filter और format कर चुका होता है; database दिखाता है कि असल में क्या store हुआ। जब कोई test fail हो, या गलत वजह से pass हो, तो एक छोटी query बता देती है कि defect data में है या उसे दिखाने वाले code में, और developer को दोबारा चलाने लायक evidence देती है।
SELECT वह जगह भी है जहाँ beginners चुपचाप गलतियाँ करते हैं: = NULL लिखी condition, छूटे हुए parentheses या ORDER BY के बिना पढ़ी गई list कोई error नहीं देती। वह गलत rows लौटाती है, और उन पर भरोसा करने वाला tester टूटे feature को pass कर देता है या ऐसा bug report करता है जो है ही नहीं।
SELECT statement कैसे बनता है
SQL declarative है: आप result बताते हैं और database तय करता है कि उसे कैसे बनाना है। Language को standard ISO/IEC 9075 परिभाषित करता है; PostgreSQL, MySQL, SQLite या SQL Server जैसा हर engine इसकी एक dialect implement करता है, और यहाँ की basics सबमें चलती हैं, जब तक कोई note कुछ और न कहे।
Statement clauses से बनता है जो keywords से शुरू होते हैं। Keywords पर case का असर नहीं पड़ता, पर capitals से query पढ़ना आसान होता है। Text single quotes में जाता है ('PAID'); standard SQL और PostgreSQL में double quotes का मतलब column या table का नाम है। -- से comment शुरू होता है और ; statement ख़त्म करता है। Result खुद एक table है, और zero rows एक valid जवाब है, error नहीं।
Clauses logically उस क्रम से अलग क्रम में evaluate होते हैं जिसमें वे लिखे जाते हैं: FROM, WHERE, SELECT list, ORDER BY, फिर LIMIT। इसलिए SELECT list में AS से बना alias ORDER BY में चलता है पर WHERE में नहीं, जो alias बनने से पहले चलता है। PostgreSQL और MySQL वहाँ इसे reject करते हैं; SQLite इसे स्वीकार करता है, इसलिए SQLite पर practice में चलने वाली query project के engine पर fail हो सकती है।
Customer 207 के paid orders, सबसे नए पहले
-- Paid orders of customer 207, newest first भाग 3:SELECT order_id, total_amount AS total, created_at भाग 1:FROM orders भाग 2:WHERE customer_id = 207 AND status = 'PAID' भाग 4:ORDER BY created_at DESC, order_id DESC भाग 5:LIMIT 5;
- 1–2कौन-सी rows
- 3कौन-से columns
- 4–5किस क्रम में, और कितनी
- 1
FROM: tableसबसे पहले evaluate होता है: वह table बताता है जिसकी rows पर बाद के सभी clauses काम करते हैं।लिखने में दूसरा - 2
WHERE: rowsसिर्फ़ वे rows रखता है जिनके लिए पूरी condition true हो; जहाँ वह false हो याNULLके कारण unknown, वे rows हट जाती हैं।लिखने में तीसरा - 3
SELECTlist: columnsColumns और उनके नाम चुनता है। Aliastotalयहीं से मौजूद है, इसलिएORDER BYइसे इस्तेमाल कर सकता है; standard SQL इसेWHEREमें इस्तेमाल करने नहीं देती।लिखने में पहला - 4
ORDER BY: क्रमसबसे नया पहले;order_id DESCएक ही पल में बने orders के बीच tie तोड़ता है। इस clause के बिना क्रम तय नहीं होता।लिखने में चौथा - 5
LIMIT: कितनी rowsSorted result की पहली 5 rows रखता है। SQL ServerTOP (5)लिखता है; standard रूपFETCH FIRST 5 ROWS ONLYहै।लिखने में पाँचवाँ
नंबर वह logical क्रम दिखाते हैं जो result तय करता है, वह क्रम नहीं जिसमें engine असल में data पढ़ता है।
पाठ संस्करण
-- Paid orders of customer 207, newest first
SELECT order_id, total_amount AS total, created_at
FROM orders
WHERE customer_id = 207
AND status = 'PAID'
ORDER BY created_at DESC, order_id DESC
LIMIT 5;SELECT से columns और WHERE से rows चुनना
जिन columns को check करते हैं उनके नाम लिखें, जैसे SELECT order_id, status, और SELECT * सिर्फ़ जल्दी नज़र डालने के लिए रखें, ताकि saved checks bug report में पढ़ने लायक रहें। AS output column का नाम बदलता है, और SELECT DISTINCT status FROM orders हर value एक बार दिखाता है: ऐसी values पकड़ने का तेज़ तरीका जिनकी किसी ने उम्मीद नहीं की थी, जैसे 'CANCELLED' के बगल में 'CANCELED'।
WHERE हर row के लिए evaluate होता है, और सिर्फ़ वे rows लौटती हैं जिनके लिए वह true हो। यह इन हिस्सों से बनता है:
- Comparisons:
=,<>(ज़्यादातर engines!=भी स्वीकार करते हैं),<,<=,>,>=। - Logic:
ANDORसे पहले evaluate होता है, इसलिएstatus = 'PAID' OR status = 'SHIPPED' AND total_amount > 500सारे paid orders और 500 से ऊपर के shipped orders लौटाता है। जो मतलब है उसे parentheses से साफ़ करें। - Lists और ranges:
status IN ('PAID', 'SHIPPED');BETWEEN 100 AND 300में दोनों सिरे शामिल हैं। Timestamps के लिए half-open range इस्तेमाल करें, जिसमें शुरुआत शामिल हो और अंत नहीं:created_at >= '2026-09-01' AND created_at < '2026-10-01'। - Patterns:
LIKE '%@example.com', जहाँ%characters की कोई भी sequence (खाली भी) और_ठीक एक character match करता है। Case sensitivity engine और column के collation पर निर्भर है, यानी text को compare और sort करने के उसके नियम: PostgreSQL text को case-sensitive तरीके से compare करता है, MySQL के default collations नहीं, और SQLite मेंLIKEASCII letters का case नहीं देखता जबकि=देखता है।
ORDER BY से result sort करना
ORDER BY के बिना rows का क्रम तय नहीं होता: data बढ़ने, index (वह structure जिससे database rows जल्दी ढूँढता है) जुड़ने या engine upgrade होने पर वह बदल सकता है। जो check “पहली row” पढ़ता है या किसी list की screen से तुलना करता है, उसे साफ़ तौर पर sort करना चाहिए।
ORDER BY created_at DESC, order_id DESC दूसरा column तभी इस्तेमाल करता है जब पहला बराबर हो; ASC default है। अंत में primary key जैसा unique column रखें: इस tie-breaker के बिना बराबर rows हर run में जगह बदल सकती हैं, और paging में कोई row दो pages पर या किसी पर भी नहीं दिख सकती।
LIMIT 10sorting के बाद पहली दस rows रखता है। SQL ServerTOP (10)लिखता है; standard रूपFETCH FIRST 10 ROWS ONLYPostgreSQL में चलता है, MySQL और SQLite में नहीं।- Text column के collation से sort होता है, और text के रूप में stored numbers text की तरह sort होते हैं:
'10''9'से पहले आता है। Screen पर ऐसे sort हुई price list column का data type जाँचने की वजह है।
NULL: वह value जो मौजूद नहीं
NULL किसी missing या unknown value को दर्शाता है; यह zero नहीं, खाली string '' नहीं और text 'NULL' भी नहीं। NULL से comparison न true होता है न false, बल्कि unknown, और WHERE सिर्फ़ true rows रखता है, इसलिए जिन rows में compare किया गया column NULL है, वे बिना किसी चेतावनी के results से गायब हो जाती हैं।
Unknown AND और OR से होकर भी आगे जाता है। AND तभी true होता है जब दोनों तरफ़ true हों, इसलिए true AND unknown unknown है और row हट जाती है; OR को एक true तरफ़ काफ़ी है, इसलिए unknown OR true true है और row रहती है।
WHERE email = NULLकभी कोई row नहीं लौटाता।IS NULLऔरIS NOT NULLइस्तेमाल करें।WHERE city <> 'Riyadh'उन rows को भी हटा देता है जिनकी cityNULLहै, औरNOT (city = 'Riyadh')भी। अगर वे rows result में चाहिए, तोOR city IS NULLजोड़ें।NULLके साथ arithmetic का नतीजाNULLहै;COALESCE(delivery_fee, 0)अपना पहला ऐसा argument लौटाता है जोNULLन हो।- PostgreSQL, MySQL और SQLite में खाली string
NULLनहीं है (Oracle Database''कोNULLके रूप में store करता है), इसलिए required field का check दोनों को ढूँढता है। - Ascending order में PostgreSQL
NULLको आख़िर में रखता है, MySQL और SQLite शुरू में; descending order में हर engine इसका उल्टा करता है। Position साफ़ तय करने के लिए PostgreSQL और SQLiteNULLS FIRSTयाNULLS LASTस्वीकार करते हैं।
-- Customers without a usable email address
SELECT customer_id, full_name
FROM customers
WHERE email IS NULL OR email = '';
-- Show a default where the value is missing
SELECT order_id, COALESCE(coupon_code, 'none') AS coupon
FROM orders
WHERE customer_id = 207;Worked example: “My orders” page की जाँच
Requirement: “My orders customer के orders दिखाता है, cancelled छोड़कर, सबसे नया पहले; एक ही समय पर बने orders order number से आते हैं, सबसे बड़ा पहले; एक page पर अधिकतम 10 orders।” Tester पहले वह query लिखता है जो test data से expected list बनाती है, ताकि test oracle, यानी expected result का source, नियम से आए, screen से नहीं।
Customer 207 के पाँच orders हैं; order 1003 किसी दूसरे customer का है। Query की हर line नियम का एक हिस्सा जाँचती है:
customer_id = 207: अगर order 1003 दिखे, तो एक customer दूसरे customer का data देख रहा है — यह privacy defect है।status <> 'CANCELLED': order 1002 expected नहीं है। यहाँstatusNOT NULLहै; अगर यहNULLस्वीकार करता, तो यही condition बिना status वाले orders भी छिपा देती।ORDER BY created_at DESC, order_id DESC: 1004 और 1005 काcreated_atएक ही है, इसलिए tie-breaker 1005 को पहले रखता है। जो page 1004 पहले दिखाए, या reload पर दोनों की जगह बदल दे, वह नियम तोड़ता है।LIMIT 10: page size एक boundary है। Boundary value analysis की तरह ठीक 10 और 11 non-cancelled orders से test करें: 11वाँ order दूसरे page पर आना चाहिए, और कोई order दो बार नहीं।LIMIT 10 OFFSET 10पहली दस rows छोड़कर expected दूसरा page देता है।
-- Test data: orders
-- order_id customer_id status total_amount created_at
-- 1001 207 PAID 120.00 2026-09-03 10:15
-- 1002 207 CANCELLED 80.00 2026-09-05 18:40
-- 1003 311 PAID 455.50 2026-09-06 09:05
-- 1004 207 SHIPPED 455.50 2026-09-12 21:30
-- 1005 207 PAID 60.00 2026-09-12 21:30
-- 1006 207 PAID 35.25 2026-09-20 08:00
SELECT order_id, status, total_amount, created_at
FROM orders
WHERE customer_id = 207
AND status <> 'CANCELLED'
ORDER BY created_at DESC, order_id DESC
LIMIT 10;
-- Expected, top to bottom: 1006, 1005, 1004, 1001आम गलतियाँ
= NULLया<> NULLलिखना: query zero rows लौटाती है, और zero rows की उम्मीद करने वाला check गलत वजह से pass हो जाता है।- भूल जाना कि
<>औरNOTउन rows को भी हटा देते हैं जहाँ columnNULLहै। ORDER BYया tie-breaker के बिना result की screen से तुलना करना, और फिर ऐसा sorting bug report करना जो असल में undefined order है।ANDऔरORको बिना parentheses मिलाना, जिससे filter वे rows लौटाता है जिन्हें requirement बाहर रखती है।- Timestamp column पर
BETWEEN '2026-09-01' AND '2026-09-30'इस्तेमाल करना: इससे 30 सितंबर को 00:00 के बाद की हर row छूट जाती है। - बिना control के खाली result पर भरोसा करना:
'CANCELLED'की जगह'CANCELED'जैसी गलत spelling वाली value भी zero rows लौटाती है। पहले ऐसी row query करें जिसके होने का आपको पता है।
QA का नज़रिया
Testers SELECT का इस्तेमाल tests तैयार करने (data चुनने और expected results निकालने), किसी action ने क्या store किया यह confirm करने, जैसा CRUD operations वाले lesson में देखा, और failure की जाँच में data problem को display problem से अलग करने के लिए करते हैं। यह सब पढ़ना है: test environment में read-only account इस्तेमाल करें, और सुविधा के लिए कभी production का personal data न खंगालें।
Query को test evidence मानें: statement, environment और लौटी rows को test case या bug report में रखें, ताकि developer उसे दोबारा चला सके। Developers से पूछें कि कौन-से columns NULL हो सकते हैं, और product owner से पूछें कि value missing होने पर users को क्या दिखना चाहिए; वही जवाब आपके NULL cases का expected result है।
अभ्यास
Email campaign वाली query का review
Marketing team Riyadh के बाहर के हर उस customer को email भेजना चाहती है जिसके पास email address है, सबसे ज़्यादा loyalty points वाले पहले। छह sample rows के आधार पर अनुमान लगाएँ कि नीचे दी गई developer की query क्या लौटाएगी, उसके defects खोजें, और result के साथ सुधरी हुई query लिखें।
कुछ defects असल में requirement के बारे में सवाल हैं: उन्हें product owner के लिए लिखें।
-- Test data: customers
-- customer_id full_name city email loyalty_points
-- 1 Layla Hassan Riyadh layla@example.com 120
-- 2 Omar Saleh Jeddah NULL 300
-- 3 Priya Nair Dammam '' NULL
-- 4 Khalid Ali NULL khalid@example.com 450
-- 5 Sara Ahmed Jeddah sara@example.com 75
-- 6 Rahul Mehta Dammam rahul@example.com NULL
-- The developer's query
SELECT customer_id, full_name, email
FROM customers
WHERE city <> 'Riyadh' AND email <> NULL
ORDER BY loyalty_points;- हर row के लिए WHERE condition का हर हिस्सा evaluate करें: true, false या unknown।
- Query जो rows लौटाती है, उन्हें लिखें।
- Defects और उनसे उठने वाले requirement के सवाल लिखें।
- सुधरी हुई query और उसकी rows क्रम से लिखें।
मॉडल उत्तर दिखाएँ
city <> 'Riyadh' row 1 के लिए false, rows 2, 3, 5 और 6 के लिए true, और row 4 के लिए unknown है; email <> NULL हर row के लिए unknown है।
AND तभी true होता है जब दोनों तरफ़ true हों, इसलिए कोई row qualify नहीं करती: query कोई row नहीं लौटाती, और कोई चेतावनी भी नहीं मिलती।
Defects: email <> NULL को email IS NOT NULL होना चाहिए; customer 3 की खाली string NULL नहीं है, इसलिए email = '' को भी बाहर करें; sort DESC होना चाहिए; customer 6 के NULL points engine के हिसाब से पहले या आख़िर में आते हैं; और बराबर points के लिए कोई tie-breaker नहीं है।
Product owner से सवाल: क्या बिना city वाला customer (customer 4) Riyadh के बाहर गिना जाए? क्या missing loyalty points को 0 माना जाए?
अगर दोनों जवाब हाँ हैं, तो SELECT customer_id, full_name, email FROM customers WHERE (city <> 'Riyadh' OR city IS NULL) AND email IS NOT NULL AND email <> '' ORDER BY COALESCE(loyalty_points, 0) DESC, customer_id; customers 4 (450 points), 5 (75) और 6 (कोई points नहीं) इसी क्रम में लौटाती है। अगर बिना city वाले customers बाहर रखे जाएँ, तो result 5, फिर 6 है।
अक्सर पूछे जाने वाले सवाल
क्या मुझे किसी ख़ास database की SQL सीखनी होगी?
अपने project के engine से शुरू करें। SELECT, WHERE, ORDER BY और IS NULL, PostgreSQL, MySQL, SQLite, SQL Server और Oracle Database में एक ही तरह लिखे जाते हैं; सबसे पहले मिलने वाले अंतर हैं row limits, date functions, text comparison की case sensitivity और NULLs की sort position। जब कोई query एक project से दूसरे में जाए, तो इन्हें अपने engine के documentation में जाँचें।
क्या shared database पर SELECT चलाना safe है?
SELECT data नहीं बदलता, पर उसकी भी क़ीमत है: selective WHERE के बिना बड़ी table पर query सबके लिए database धीमा कर सकती है, और rows में personal data हो सकता है। Read-only account इस्तेमाल करें, primary key या date range पर filter करें, explore करते समय LIMIT जोड़ें, और production access के लिए अपनी team के नियम मानें।
Database server के बिना practice कैसे करूँ?
SQLite पूरा database एक file में रखता है और उसे server की ज़रूरत नहीं, बस उसका command-line shell sqlite3 काफ़ी है, इसलिए practice के लिए यह आम पसंद है। Table और sample rows SQL script के रूप में generate करें, उन्हें load करें, और इस lesson की queries दोबारा चलाएँ — हर result का अनुमान पहले लगाकर। याद रखें कि कुछ जगहों पर SQLite ज़्यादातर engines जितना सख़्त नहीं है, जैसे WHERE में alias स्वीकार करना।
संदर्भ
- ISO/IEC 9075-1:2023 — Information technology — Database languages SQL — Part 1: Framework (SQL/Framework)अंतरराष्ट्रीय SQL मानक का framework भाग, जिसे PostgreSQL, MySQL, SQLite आदि की बोलियाँ अलग-अलग हद तक लागू करती हैं।
- PostgreSQL Documentation: SQL SyntaxPostgreSQL में SQL की लेक्सिकल संरचना: आइडेंटिफ़ायर, क्वोटिंग, स्ट्रिंग कॉन्स्टेंट और एस्केपिंग।
- SQL As Understood By SQLiteSQLite द्वारा स्वीकृत SQL व्याकरण, स्टेटमेंट दर स्टेटमेंट, सिंटैक्स डायग्राम के साथ।
Mutqan tools से अभ्यास करें
SQL स्टेटमेंट में सिंटैक्स की समस्याएँ, असंतुलित कोष्ठक, बिना बंद की स्ट्रिंग और जोखिम भरे पैटर्न जाँचें।
SQL क्वेरी को एकसमान कीवर्ड केसिंग, इंडेंटेशन और लाइन ब्रेक के साथ फ़ॉर्मेट करें (MySQL, PostgreSQL, SQL Server, Oracle, SQLite)।
किसी भी dialect के लिए वास्तविक जैसी टेस्ट पंक्तियों के साथ SQL seed स्क्रिप्ट (CREATE TABLE + INSERT) जनरेट करें।
वैल्यू की सूची (हर लाइन पर एक या कॉमा से अलग) को कोट किए SQL IN (...) क्लॉज़ में बदलें।
और गहराई से
इस topic में आपकी प्रगति
प्रगति ट्रैक करने के लिए साइन इन करें
Topics पूर्ण चिह्नित करें, जहाँ छोड़ा था वहीं से जारी रखें और specialisation परीक्षाएँ खोलें।