SQL
सामान्य टेबल एक्सप्रेशन
खोज…
वाक्य - विन्यास
QueryName [(ColumnName, ...)] AS के साथ (
चुनते हैं ...
)
चयन करें ... QueryName से ...;RECURSIVE QueryName [(ColumnName, ...)] AS के साथ (
चुनते हैं ...
यूनिअन [सभी]
चयन करें ... QueryName से ...
)
चयन करें ... QueryName से ...;
टिप्पणियों
आधिकारिक दस्तावेज: खंड के साथ
कॉमन टेबल एक्सप्रेशन एक अस्थायी परिणाम सेट है, और यह जटिल उप क्वेरी का परिणाम हो सकता है। इसे खण्ड के साथ प्रयोग करके परिभाषित किया गया है। CTE पठनीयता में सुधार करता है और यह TempDB डेटाबेस के बजाय मेमोरी में बनाया जाता है जहाँ Temp Table और Table वेरिएबल बनाया जाता है।
सामान्य टेबल एक्सप्रेशन की मुख्य अवधारणाएँ:
- जटिल प्रश्नों को तोड़ने के लिए इस्तेमाल किया जा सकता है, विशेष रूप से जटिल जुड़ाव और उप-प्रश्न।
- एक क्वेरी परिभाषा एन्कैप्सुलेट करने का एक तरीका है।
- केवल तब तक जारी रखें जब तक कि अगली क्वेरी न चला दी जाए।
- सही उपयोग से कोड गुणवत्ता / स्थिरता और गति दोनों में सुधार हो सकता है।
- एक ही बयान में परिणामी तालिका को कई बार संदर्भित करने के लिए इस्तेमाल किया जा सकता है (SQL में दोहराव को समाप्त करें)।
- जब दृश्य के सामान्य उपयोग की आवश्यकता नहीं है, तो एक दृश्य के लिए एक विकल्प हो सकता है; यही है, आपको मेटाडेटा में परिभाषा को संग्रहीत करने की आवश्यकता नहीं है।
- जब बुलाया जाएगा, तब चलाया जाएगा जब परिभाषित नहीं किया जाएगा। यदि CTE को क्वेरी में कई बार उपयोग किया जाता है तो इसे कई बार (संभवतः विभिन्न परिणामों के साथ) चलाया जाएगा।
अस्थायी क्वेरी
ये नेस्टेड सबक्वेरीज़ के समान ही व्यवहार करते हैं लेकिन एक अलग सिंटैक्स के साथ।
WITH ReadyCars AS (
SELECT *
FROM Cars
WHERE Status = 'READY'
)
SELECT ID, Model, TotalCost
FROM ReadyCars
ORDER BY TotalCost;
आईडी | नमूना | कुल लागत |
---|---|---|
1 | फोर्ड एफ -150 | 200 |
2 | फोर्ड एफ -150 | 230 |
समतुल्य उपशम वाक्य-विन्यास
SELECT ID, Model, TotalCost
FROM (
SELECT *
FROM Cars
WHERE Status = 'READY'
) AS ReadyCars
ORDER BY TotalCost
एक पेड़ में पुनरावर्ती जा रहा है
WITH RECURSIVE ManagersOfJonathon AS (
-- start with this row
SELECT *
FROM Employees
WHERE ID = 4
UNION ALL
-- get manager(s) of all previously selected rows
SELECT Employees.*
FROM Employees
JOIN ManagersOfJonathon
ON Employees.ID = ManagersOfJonathon.ManagerID
)
SELECT * FROM ManagersOfJonathon;
ईद | fName | LName | फ़ोन नंबर | प्रबंधक- | DepartmentId |
---|---|---|---|---|---|
4 | Johnathon | लोहार | 1212121212 | 2 | 1 |
2 | जॉन | जॉनसन | 2468101214 | 1 | 1 |
1 | जेम्स | लोहार | 1 2 3 4 5 6 7 8 9 0 | शून्य | 1 |
मान पैदा करना
अधिकांश डेटाबेस में तदर्थ उपयोग के लिए संख्याओं की एक श्रृंखला उत्पन्न करने का एक देशी तरीका नहीं है; हालाँकि, सामान्य तालिका अभिव्यक्तियों का उपयोग उस प्रकार के फ़ंक्शन का अनुकरण करने के लिए पुनरावर्तन के साथ किया जा सकता है।
निम्न उदाहरण एक आम तालिका अभिव्यक्ति बुलाया उत्पन्न करता है Numbers
एक स्तंभ के साथ i
जो संख्या 1-5 के लिए एक पंक्ति है:
--Give a table name `Numbers" and a column `i` to hold the numbers
WITH Numbers(i) AS (
--Starting number/index
SELECT 1
--Top-level UNION ALL operator required for recursion
UNION ALL
--Iteration expression:
SELECT i + 1
--Table expression we first declared used as source for recursion
FROM Numbers
--Clause to define the end of the recursion
WHERE i < 5
)
--Use the generated table expression like a regular table
SELECT i FROM Numbers;
मैं |
---|
1 |
2 |
3 |
4 |
5 |
इस पद्धति का उपयोग किसी भी संख्या के अंतराल के साथ-साथ अन्य प्रकार के डेटा के साथ किया जा सकता है।
एक उपसमुच्चय की पुनरावृत्ति
WITH RECURSIVE ManagedByJames(Level, ID, FName, LName) AS (
-- start with this row
SELECT 1, ID, FName, LName
FROM Employees
WHERE ID = 1
UNION ALL
-- get employees that have any of the previously selected rows as manager
SELECT ManagedByJames.Level + 1,
Employees.ID,
Employees.FName,
Employees.LName
FROM Employees
JOIN ManagedByJames
ON Employees.ManagerID = ManagedByJames.ID
ORDER BY 1 DESC -- depth-first search
)
SELECT * FROM ManagedByJames;
स्तर | आईडी | fName | LName |
---|---|---|---|
1 | 1 | जेम्स | लोहार |
2 | 2 | जॉन | जॉनसन |
3 | 4 | Johnathon | लोहार |
2 | 3 | माइकल | विलियम्स |
Oracle पुनरावर्ती CTEs के साथ कार्यक्षमता द्वारा कनेक्ट
Oracle के CONNECT BY कार्यक्षमता SQL मानक पुनरावर्ती CTE का उपयोग करते समय अंतर्निहित नहीं होने वाली कई उपयोगी और nontrivial सुविधाएँ प्रदान करता है। यह उदाहरण SQL सर्वर सिंटैक्स का उपयोग करके इन सुविधाओं (संपूर्णता के लिए कुछ अतिरिक्त के साथ) को दोहराता है। यह ओरेकल डेवलपर्स के लिए अन्य डेटाबेस पर उनके पदानुक्रमित प्रश्नों में गायब कई विशेषताओं को खोजने के लिए सबसे उपयोगी है, लेकिन यह सामान्य रूप से पदानुक्रमित क्वेरी के साथ क्या किया जा सकता है यह दिखाने के लिए भी कार्य करता है।
WITH tbl AS (
SELECT id, name, parent_id
FROM mytable)
, tbl_hierarchy AS (
/* Anchor */
SELECT 1 AS "LEVEL"
--, 1 AS CONNECT_BY_ISROOT
--, 0 AS CONNECT_BY_ISBRANCH
, CASE WHEN t.id IN (SELECT parent_id FROM tbl) THEN 0 ELSE 1 END AS CONNECT_BY_ISLEAF
, 0 AS CONNECT_BY_ISCYCLE
, '/' + CAST(t.id AS VARCHAR(MAX)) + '/' AS SYS_CONNECT_BY_PATH_id
, '/' + CAST(t.name AS VARCHAR(MAX)) + '/' AS SYS_CONNECT_BY_PATH_name
, t.id AS root_id
, t.*
FROM tbl t
WHERE t.parent_id IS NULL -- START WITH parent_id IS NULL
UNION ALL
/* Recursive */
SELECT th."LEVEL" + 1 AS "LEVEL"
--, 0 AS CONNECT_BY_ISROOT
--, CASE WHEN t.id IN (SELECT parent_id FROM tbl) THEN 1 ELSE 0 END AS CONNECT_BY_ISBRANCH
, CASE WHEN t.id IN (SELECT parent_id FROM tbl) THEN 0 ELSE 1 END AS CONNECT_BY_ISLEAF
, CASE WHEN th.SYS_CONNECT_BY_PATH_id LIKE '%/' + CAST(t.id AS VARCHAR(MAX)) + '/%' THEN 1 ELSE 0 END AS CONNECT_BY_ISCYCLE
, th.SYS_CONNECT_BY_PATH_id + CAST(t.id AS VARCHAR(MAX)) + '/' AS SYS_CONNECT_BY_PATH_id
, th.SYS_CONNECT_BY_PATH_name + CAST(t.name AS VARCHAR(MAX)) + '/' AS SYS_CONNECT_BY_PATH_name
, th.root_id
, t.*
FROM tbl t
JOIN tbl_hierarchy th ON (th.id = t.parent_id) -- CONNECT BY PRIOR id = parent_id
WHERE th.CONNECT_BY_ISCYCLE = 0) -- NOCYCLE
SELECT th.*
--, REPLICATE(' ', (th."LEVEL" - 1) * 3) + th.name AS tbl_hierarchy
FROM tbl_hierarchy th
JOIN tbl CONNECT_BY_ROOT ON (CONNECT_BY_ROOT.id = th.root_id)
ORDER BY th.SYS_CONNECT_BY_PATH_name; -- ORDER SIBLINGS BY name
कनेक्ट की गई विशेषताओं के ऊपर, स्पष्टीकरण के साथ:
- खंड
- कनेक्ट द्वारा: पदानुक्रम को परिभाषित करने वाले संबंध को निर्दिष्ट करता है।
- स्टार्ट विथ: रूट नोड्स को निर्दिष्ट करता है।
- आदेश द्वारा आदेश: आदेश ठीक से परिणाम।
- पैरामीटर
- NOCYCLE: लूप का पता चलने पर एक शाखा को संसाधित करता है। वैध पदानुक्रम निर्देशित चक्रीय रेखांकन हैं, और परिपत्र संदर्भ इस निर्माण का उल्लंघन करते हैं।
- ऑपरेटर्स
- PRIOR: नोड के माता-पिता से डेटा प्राप्त करता है।
- CONNECT_BY_ROOT: नोड के रूट से डेटा प्राप्त करता है।
- Pseudocolumns
- स्तर: नोड की जड़ से इसकी दूरी को इंगित करता है।
- CONNECT_BY_ISLEAF: बच्चों के बिना एक नोड इंगित करता है।
- CONNECT_BY_ISCYCLE: एक नोड को एक परिपत्र संदर्भ के साथ इंगित करता है।
- कार्य
- SYS_CONNECT_BY_PATH: अपने रूट से नोड के लिए पथ का समतल / समतल प्रतिनिधित्व करता है।
उदाहरण के रूप में टीम रोस्ट्रिंग को शामिल करने के लिए विस्तृत रूप से तारीखें उत्पन्न करें
DECLARE @DateFrom DATETIME = '2016-06-01 06:00'
DECLARE @DateTo DATETIME = '2016-07-01 06:00'
DECLARE @IntervalDays INT = 7
-- Transition Sequence = Rest & Relax into Day Shift into Night Shift
-- RR (Rest & Relax) = 1
-- DS (Day Shift) = 2
-- NS (Night Shift) = 3
;WITH roster AS
(
SELECT @DateFrom AS RosterStart, 1 AS TeamA, 2 AS TeamB, 3 AS TeamC
UNION ALL
SELECT DATEADD(d, @IntervalDays, RosterStart),
CASE TeamA WHEN 1 THEN 2 WHEN 2 THEN 3 WHEN 3 THEN 1 END AS TeamA,
CASE TeamB WHEN 1 THEN 2 WHEN 2 THEN 3 WHEN 3 THEN 1 END AS TeamB,
CASE TeamC WHEN 1 THEN 2 WHEN 2 THEN 3 WHEN 3 THEN 1 END AS TeamC
FROM roster WHERE RosterStart < DATEADD(d, -@IntervalDays, @DateTo)
)
SELECT RosterStart,
ISNULL(LEAD(RosterStart) OVER (ORDER BY RosterStart), RosterStart + @IntervalDays) AS RosterEnd,
CASE TeamA WHEN 1 THEN 'RR' WHEN 2 THEN 'DS' WHEN 3 THEN 'NS' END AS TeamA,
CASE TeamB WHEN 1 THEN 'RR' WHEN 2 THEN 'DS' WHEN 3 THEN 'NS' END AS TeamB,
CASE TeamC WHEN 1 THEN 'RR' WHEN 2 THEN 'DS' WHEN 3 THEN 'NS' END AS TeamC
FROM roster
परिणाम
Ie For Week 1 TeamA R & R पर है, TeamB डे शिफ्ट पर है और TeamC नाइट शिफ्ट पर है।
कॉमन टेबल एक्सप्रेशंस का उपयोग करने के लिए एक क्वेरी को फिर से दिखाना
मान लीजिए कि हम 20 से अधिक कुल बिक्री के साथ सभी उत्पाद श्रेणियां प्राप्त करना चाहते हैं।
यहाँ सामान्य टेबल एक्सप्रेशंस के बिना एक क्वेरी है:
SELECT category.description, sum(product.price) as total_sales
FROM sale
LEFT JOIN product on sale.product_id = product.id
LEFT JOIN category on product.category_id = category.id
GROUP BY category.id, category.description
HAVING sum(product.price) > 20
और कॉमन टेबल एक्सप्रेशंस का उपयोग करते हुए एक समान क्वेरी:
WITH all_sales AS (
SELECT product.price, category.id as category_id, category.description as category_description
FROM sale
LEFT JOIN product on sale.product_id = product.id
LEFT JOIN category on product.category_id = category.id
)
, sales_by_category AS (
SELECT category_description, sum(price) as total_sales
FROM all_sales
GROUP BY category_id, category_description
)
SELECT * from sales_by_category WHERE total_sales > 20
कॉमन टेबल एक्सप्रेशन के साथ एक जटिल एसक्यूएल का उदाहरण
मान लीजिए कि हम "सबसे सस्ते उत्पादों" को "शीर्ष श्रेणियों" से क्वेरी करना चाहते हैं।
यहां कॉमन टेबल एक्सप्रेशंस का उपयोग करके क्वेरी का एक उदाहरण दिया गया है
-- all_sales: just a simple SELECT with all the needed JOINS
WITH all_sales AS (
SELECT
product.price as product_price,
category.id as category_id,
category.description as category_description
FROM sale
LEFT JOIN product on sale.product_id = product.id
LEFT JOIN category on product.category_id = category.id
)
-- Group by category
, sales_by_category AS (
SELECT category_id, category_description,
sum(product_price) as total_sales
FROM all_sales
GROUP BY category_id, category_description
)
-- Filtering total_sales > 20
, top_categories AS (
SELECT * from sales_by_category WHERE total_sales > 20
)
-- all_products: just a simple SELECT with all the needed JOINS
, all_products AS (
SELECT
product.id as product_id,
product.description as product_description,
product.price as product_price,
category.id as category_id,
category.description as category_description
FROM product
LEFT JOIN category on product.category_id = category.id
)
-- Order by product price
, cheapest_products AS (
SELECT * from all_products
ORDER by product_price ASC
)
-- Simple inner join
, cheapest_products_from_top_categories AS (
SELECT product_description, product_price
FROM cheapest_products
INNER JOIN top_categories ON cheapest_products.category_id = top_categories.category_id
)
--The main SELECT
SELECT * from cheapest_products_from_top_categories