2. About Me
• Data Team Leader at PLYmedia
• During the last decade trained thousands of people (Israel and
abroad) various topic related to the database world.
• Managing an educational website mainly focused on the SQL
language
• Owner of Ram Kedem Training
3. About this Book
• Gathered over a period of almost 10 years
• Includes 265 pages and 100 Different
complex SQL use-cases
• First of its kind in Israel
• Aims to provide practical knowledge based
on real user experience
• Available in Hard-Copy & Online version
4. Goals
• Learn real use cases of :
• Advanced Scalar Functions
• Analytic Functions
• Group Functions
• Complex Sub-Queries
• CTE and Recursive CTE
• SET Operators
• XML tricks
6. 1.אחוז עם ערכים מציאת
• escape_character
• Is a character that is put in front of a wildcard character to indicate
that the wildcard should be interpreted as a regular character and
not as a wildcard.
• escape_character is a character expression that has no default and
must evaluate to only one character
SELECT *
FROM percent_values
WHERE id LIKE '%^%%' ESCAPE '^'
7. 1.אחוז עם ערכים מציאת
• Using square brackets
• In MSSQL the square brackets are required if you use keywords or special
chars in the column names or identifiers.
• For example, You could name a column [First Name] (with a space)
• The [ ] in LIKE can be used to specify the % should to be interpreted as a
regular character
SELECT *
FROM percent_values
WHERE id LIKE '%[%]%'
10. 2.אחת שורה לתוך ערכים איחוד
STUFF() Function
• The STUFF function deletes a sequence of characters from a source string
and then inserts another sequence of characters into the source string,
starting at a specified position.
SELECT STUFF('Hello' , 1,1,'B') => Bellow
SELECT STUFF('Hello' , 1,2,'B') => Bllo
SELECT STUFF('Hello', 2, 2, '**WORLD**') => H**WORLD**lo
SELECT STUFF('Hello', 1, 1, '') => ello
11. Correlated Sub Queries VS. Simple Sub Queries
• Correlated Subquery is a sub-query that uses values from the outer
query. the inner query has to be executed for every row of outer
query
• Simple subquery doesn't use values from the outer query and is being
calculated only once
2.אחת שורה לתוך ערכים איחוד
12. Simple Sub Query
SELECT customerName, CityID
FROM customers
WHERE CityID = (SELECT cityID FROM cities WHERE CityName = 'Tel Aviv')
• Inner – what’s the cityID of Tel Aviv ? (only once)
• Outer – Display the customerName and CityID for customers whose
CityID equals to the output of inner query
2.אחת שורה לתוך ערכים איחוד
13. Correlated Sub Query
SELECT CUST.CustomerName,
(SELECT CityName FROM Cities CT WHERE CT.CityID = CUST.CityID)
FROM customers CUST
• Inner – what’s the cityName for the FIRST row in the table ?
• Outer – Display the customerName in the FIRST row
• Inner – what’s the cityName for the SECOND row in the table ?
• Outer – Display the customerName in the SECOND row
…
2.אחת שורה לתוך ערכים איחוד
14. For XML Path
1. Get XML element string with FOR XML
• Adding FOR XML PATH to the end of a query allows you to output the
results of the query as XML elements, with the element name
contained in the PATH argument
SELECT ',' + CustomerName
FROM Customers
FOR XML PATH ('')
2.אחת שורה לתוך ערכים איחוד
15. For XML Path
2. Remove leading comma with STUFF
• The STUFF statement literally "stuffs” one string into another, replacing
characters within the first string. We, however, are using it simply to
remove the first character of the resultant list of values.
SELECT STUFF
(
(SELECT ',' + CustomerName
FROM Customers
FOR XML PATH ('')) ,1,1,''
)
2.אחת שורה לתוך ערכים איחוד
16. Putting it all together
SELECT CityID, CityName,
STUFF
(
(SELECT ',' + CustomerName
FROM Customers InCust
WHERE InCust.CityID = CT.CityID
FOR XML PATH ('')) ,1,1,''
) AS 'Customers'
FROM Cities CT
2.אחת שורה לתוך ערכים איחוד
18. CTE Basics
• A common table expression (CTE) can be thought of as a temporary
result set that is defined within the execution scope of a single
SELECT, INSERT, UPDATE, DELETE, or CREATE VIEW statement
• Using a CTE offers the advantages of improved readability and ease in
maintenance of complex queries.
• The query can be divided into separate, simple, logical building
blocks. These simple blocks can then be used to build more complex,
interim CTEs until the final result set is generated.
3.במשפט תווים כמות הצגת
19. ;WITH [CountCustomers] (col1, col2) AS
(
SELECT COUNT(*) CNT , CityID
FROM customers
GROUP BY CityID
)
SELECT *
FROM [CountCustomers]
3.במשפט תווים כמות הצגת
CTE name Column names
CTE name
Actual Query
20. ;WITH "Numbers" (id) AS
(
SELECT 1
UNION ALL
SELECT id + 1 FROM "Numbers"
WHERE id < 20
)
SELECT *
FROM "Numbers"
3.במשפט תווים כמות הצגת
CTE name Column name
CTE name
Anchor query (runs once and the results ‘seed’ the
Recursive query)
Recursive query (runs multiple times and
is the criteria for the remaining results)
UNION ALL statement to bind the Anchor and
Recursive queries together.
21. WITH "wordlen"(id) AS (
SELECT 1
UNION ALL
SELECT id + 1 FROM "wordlen"
WHERE id < (SELECT LEN('hello world'))
)
SELECT letter, COUNT(letter)
FROM
(
SELECT SUBSTRING('hello world' , id , 1) letter
FROM "wordlen"
WHERE SUBSTRING('hello world' , id , 1) <> ' '
) in_tab
GROUP BY letter
ORDER BY letter
3.במשפט תווים כמות הצגת
24. REVERSE ()
• Returns the reverse order of a string value.
• SELECT REVERSE('Hello') => 'Olleh'
REPLACE ()
• Replaces all occurrences of a specified string value with another string value.
• SELECT REPLACE('Hello World','World','SQL') => 'Hello SQL'
PARSENAME ()
• Returns the specified part of an object name
• SELECT PARSENAME('Word1.Word2.Word3.Word4',1) => 'Word4'
4.בעמודה מילים פיצול
26. SELECT FirstName,
CASE WHEN lastName IS NULL THEN NULL ELSE MiddleName END AS MiddleName,
CASE WHEN LastName IS NULL THEN MiddleName ELSE LastName END AS LastName
FROM
(
SELECT
Reverse(ParseName(Replace(Reverse(username), ' ', '.'), 1)) As FirstName
, Reverse(ParseName(Replace(Reverse(username), ' ', '.'), 2)) As MiddleName
, Reverse(ParseName(Replace(Reverse(username), ' ', '.'), 3)) As LastName
FROM users
) IN_TAB
4.בעמודה מילים פיצול
If there is no value in lastName then middleName is actually NULL
If there is no value in lastName then middleName is actually lastName
putting it all together
28. 5.ממוצעים זמנים חישוב
LEAD() Function
• LEAD provides access to a row at a given physical offset that follows
the current row. Use this analytic function in a SELECT statement to
compare values in the current row with values in a following row
Basic Usage
• LEAD(column_name) OVER (ORDER BY column_name)
29. 5.ממוצעים זמנים חישוב
Putting it all together
SELECT AVG(DIFF) AVG_DIFF
FROM
(
SELECT id,
fdate,
ISNULL(DATEDIFF(day, fdate, LEAD(fdate)
OVER (ORDER BY id)),0) DIFF
FROM FailuresLog
) IN_TAB
31. 6.מותנית להחלפה מתודות
-- 1. CASE
SELECT cid, CASE WHEN cdesc = 'black' THEN 'white' ELSE 'black' END cdesc
FROM colors
-- 2. REPLACE
SELECT cid, REPLACE (cdesc, 'black', 'white')
FROM colors
WHERE cdesc = 'black'
UNION ALL
SELECT cid, REPLACE (cdesc, 'white', 'black')
FROM colors
WHERE cdesc = 'white'
ORDER BY 1
-- 3. IIF
SELECT IIF(cdesc = 'white' , 'black' , 'white')
FROM colors
32. 6.מותנית להחלפה מתודות
-- 4. SUBQUERY
SELECT cid, (SELECT DISTINCT cdesc FROM colors in_tbl WHERE cdesc <> out_tbl.cdesc)
FROM colors out_tbl
-- 5. JOIN
SELECT c1.cid, c2.cdesc
FROM colors c1 JOIN (SELECT DISTINCT cdesc FROM colors) c2
ON c1.cdesc <> c2.cdesc
ORDER BY 1
-- 6. ISNULL / NULLIF
SELECT cid, ISNULL(NULLIF('white', cdesc), 'black')
FROM colors
33. Advanced SQL Course
• Will take place between March 21 and 28 at John-Bryce Tel-Aviv
• 3 Meetings, 17:30-21:00
• More details can be found here