Bài 7: String và DateTime Functions
1. String Functions
1.1 Basic String Functions
| Function | Purpose | Example |
|---|---|---|
LEN() | Length (without trailing spaces) | LEN('Hello ') → 5 |
DATALENGTH() | Bytes in string | DATALENGTH(N'Việt Nam') → 16 |
LEFT() | Left n characters | LEFT('Hello', 2) → 'He' |
RIGHT() | Right n characters | RIGHT('Hello', 2) → 'lo' |
SUBSTRING() | Extract portion | SUBSTRING('Hello', 2, 3) → 'ell' |
UPPER() | Uppercase | UPPER('hello') → 'HELLO' |
LOWER() | Lowercase | LOWER('HELLO') → 'hello' |
LTRIM() | Remove leading spaces | LTRIM(' Hello') → 'Hello' |
RTRIM() | Remove trailing spaces | RTRIM('Hello ') → 'Hello' |
TRIM() | Remove both (SQL 2017+) | TRIM(' Hello ') → 'Hello' |
1.2 String Functions với AdventureWorks
SQL
1-- Tên employee uppercase2SELECT 3 BusinessEntityID,4 UPPER(FirstName) AS FirstName_Upper,5 LOWER(LastName) AS LastName_Lower,6 LEN(FirstName) AS FirstNameLength7FROM Person.Person8WHERE PersonType = 'EM'9ORDER BY LastName;SQL
1-- Extract first 3 characters của product number2SELECT 3 ProductID,4 ProductNumber,5 LEFT(ProductNumber, 2) AS ProductPrefix,6 SUBSTRING(ProductNumber, 4, 4) AS ProductCode7FROM Production.Product8WHERE ProductNumber LIKE 'BK-%';1.3 CONCAT và String Concatenation
SQL
1-- Method 1: + operator (NULL propagates)2SELECT FirstName + ' ' + LastName AS FullName3FROM Person.Person;45-- Method 2: CONCAT (ignores NULL)6SELECT CONCAT(FirstName, ' ', MiddleName, ' ', LastName) AS FullName7FROM Person.Person;89-- Method 3: CONCAT_WS (with separator, SQL 2017+)10SELECT CONCAT_WS(' ', FirstName, MiddleName, LastName) AS FullName11FROM Person.Person;1.4 CHARINDEX và PATINDEX
SQL
1-- CHARINDEX: Tìm vị trí substring2SELECT 3 EmailAddress,4 CHARINDEX('@', EmailAddress) AS AtPosition,5 LEFT(EmailAddress, CHARINDEX('@', EmailAddress) - 1) AS Username,6 SUBSTRING(EmailAddress, CHARINDEX('@', EmailAddress) + 1, 100) AS Domain7FROM Person.EmailAddress;89-- PATINDEX: Tìm pattern (supports wildcards)10SELECT 11 Name,12 PATINDEX('%[0-9]%', Name) AS FirstDigitPosition13FROM Production.Product14WHERE PATINDEX('%[0-9]%', Name) > 0;1.5 REPLACE và STUFF
SQL
1-- REPLACE: Thay thế tất cả occurrences2SELECT 3 Name,4 REPLACE(Name, 'Mountain', 'MTN') AS ShortName5FROM Production.Product6WHERE Name LIKE '%Mountain%';78-- STUFF: Thay thế tại vị trí cụ thể9SELECT 10 PhoneNumber,11 STUFF(PhoneNumber, 1, 3, '***') AS MaskedPhone12FROM Person.PersonPhone;1.6 STRING_AGG (SQL 2017+)
SQL
1-- Combine products trong mỗi category thành 1 string2SELECT 3 pc.Name AS Category,4 STRING_AGG(p.Name, ', ') WITHIN GROUP (ORDER BY p.Name) AS Products5FROM Production.Product p6JOIN Production.ProductSubcategory ps ON p.ProductSubcategoryID = ps.ProductSubcategoryID7JOIN Production.ProductCategory pc ON ps.ProductCategoryID = pc.ProductCategoryID8WHERE p.ListPrice > 20009GROUP BY pc.ProductCategoryID, pc.Name;1.7 FORMAT (cho strings)
SQL
1-- Format phone numbers2SELECT 3 PhoneNumber,4 FORMAT(CAST(REPLACE(REPLACE(REPLACE(PhoneNumber, '-', ''), '(', ''), ')', '') AS BIGINT), '(###) ###-####') AS FormattedPhone5FROM Person.PersonPhone6WHERE LEN(REPLACE(REPLACE(REPLACE(PhoneNumber, '-', ''), '(', ''), ')', '')) = 10;2. DateTime Functions
2.1 Get Current Date/Time
| Function | Returns | Example Result |
|---|---|---|
GETDATE() | Current datetime | 2024-01-15 14:30:45.123 |
GETUTCDATE() | UTC datetime | 2024-01-15 21:30:45.123 |
SYSDATETIME() | High precision datetime2 | 2024-01-15 14:30:45.1234567 |
CURRENT_TIMESTAMP | Same as GETDATE() | 2024-01-15 14:30:45.123 |
SQL
1SELECT 2 GETDATE() AS CurrentLocal,3 GETUTCDATE() AS CurrentUTC,4 SYSDATETIME() AS HighPrecision;2.2 Date Parts Functions
SQL
1-- Extract parts2SELECT 3 OrderDate,4 YEAR(OrderDate) AS Year,5 MONTH(OrderDate) AS Month,6 DAY(OrderDate) AS Day,7 DATEPART(QUARTER, OrderDate) AS Quarter,8 DATEPART(WEEK, OrderDate) AS WeekOfYear,9 DATEPART(WEEKDAY, OrderDate) AS DayOfWeek,10 DATENAME(MONTH, OrderDate) AS MonthName,11 DATENAME(WEEKDAY, OrderDate) AS DayName12FROM Sales.SalesOrderHeader13WHERE SalesOrderID = 43659;2.3 Date Calculations với DATEADD
SQL
1-- DATEADD(interval, number, date)2SELECT 3 OrderDate,4 DATEADD(DAY, 7, OrderDate) AS Plus7Days,5 DATEADD(MONTH, 1, OrderDate) AS Plus1Month,6 DATEADD(YEAR, -1, OrderDate) AS Minus1Year,7 DATEADD(QUARTER, 1, OrderDate) AS Plus1Quarter8FROM Sales.SalesOrderHeader9WHERE SalesOrderID = 43659;Common intervals: YEAR, QUARTER, MONTH, WEEK, DAY, HOUR, MINUTE, SECOND
2.4 Date Difference với DATEDIFF
SQL
1-- Orders với số ngày để ship2SELECT 3 SalesOrderID,4 OrderDate,5 ShipDate,6 DATEDIFF(DAY, OrderDate, ShipDate) AS DaysToShip,7 DATEDIFF(HOUR, OrderDate, ShipDate) AS HoursToShip8FROM Sales.SalesOrderHeader9WHERE ShipDate IS NOT NULL10ORDER BY DaysToShip DESC;SQL
1-- Customer age analysis (days since first order)2SELECT 3 CustomerID,4 MIN(OrderDate) AS FirstOrder,5 MAX(OrderDate) AS LastOrder,6 DATEDIFF(DAY, MIN(OrderDate), MAX(OrderDate)) AS CustomerLifespanDays,7 DATEDIFF(MONTH, MIN(OrderDate), MAX(OrderDate)) AS CustomerLifespanMonths8FROM Sales.SalesOrderHeader9GROUP BY CustomerID10HAVING COUNT(*) > 511ORDER BY CustomerLifespanDays DESC;2.5 Date Formatting với FORMAT
SQL
1SELECT 2 OrderDate,3 FORMAT(OrderDate, 'yyyy-MM-dd') AS ISO_Format,4 FORMAT(OrderDate, 'dd/MM/yyyy') AS EU_Format,5 FORMAT(OrderDate, 'MMMM dd, yyyy') AS Long_Format,6 FORMAT(OrderDate, 'yyyy-MM') AS YearMonth,7 FORMAT(OrderDate, 'dddd') AS DayName8FROM Sales.SalesOrderHeader9WHERE SalesOrderID = 43659;Common format patterns:
yyyy- 4-digit yearMM- 2-digit monthdd- 2-digit dayMMMM- Full month namedddd- Full day nameHH:mm:ss- 24-hour time
2.6 EOMONTH (End of Month)
SQL
1-- End of month calculations2SELECT 3 OrderDate,4 EOMONTH(OrderDate) AS EndOfMonth,5 EOMONTH(OrderDate, 1) AS EndOfNextMonth,6 EOMONTH(OrderDate, -1) AS EndOfPrevMonth,7 DAY(EOMONTH(OrderDate)) AS DaysInMonth8FROM Sales.SalesOrderHeader9WHERE SalesOrderID = 43659;2.7 Date Construction
SQL
1-- DATEFROMPARTS, DATETIME2FROMPARTS2SELECT 3 DATEFROMPARTS(2024, 1, 15) AS ConstructedDate,4 DATETIME2FROMPARTS(2024, 1, 15, 14, 30, 0, 0, 0) AS ConstructedDateTime;2.8 ISDATE Validation
SQL
1-- Check if string is valid date2SELECT 3 '2024-01-15' AS TestValue,4 ISDATE('2024-01-15') AS IsValidDate,5 ISDATE('invalid') AS InvalidDate,6 ISDATE('2024-02-30') AS Feb30;3. Practical DateTime Scenarios
3.1 Fiscal Year Analysis
SQL
1-- Assuming fiscal year starts April 12WITH FiscalData AS (3 SELECT 4 OrderDate,5 TotalDue,6 CASE 7 WHEN MONTH(OrderDate) >= 4 THEN YEAR(OrderDate)8 ELSE YEAR(OrderDate) - 19 END AS FiscalYear,10 CASE 11 WHEN MONTH(OrderDate) >= 4 THEN MONTH(OrderDate) - 312 ELSE MONTH(OrderDate) + 913 END AS FiscalMonth14 FROM Sales.SalesOrderHeader15)16SELECT 17 FiscalYear,18 FiscalMonth,19 SUM(TotalDue) AS Revenue20FROM FiscalData21GROUP BY FiscalYear, FiscalMonth22ORDER BY FiscalYear, FiscalMonth;3.2 Same Day Last Year Comparison
SQL
1WITH CurrentYearSales AS (2 SELECT 3 CAST(OrderDate AS DATE) AS OrderDate,4 SUM(TotalDue) AS Revenue5 FROM Sales.SalesOrderHeader6 WHERE YEAR(OrderDate) = 20147 GROUP BY CAST(OrderDate AS DATE)8),9PreviousYearSales AS (10 SELECT 11 CAST(OrderDate AS DATE) AS OrderDate,12 SUM(TotalDue) AS Revenue13 FROM Sales.SalesOrderHeader14 WHERE YEAR(OrderDate) = 201315 GROUP BY CAST(OrderDate AS DATE)16)17SELECT 18 c.OrderDate AS CurrentDate,19 c.Revenue AS CurrentRevenue,20 p.Revenue AS PrevYearRevenue,21 c.Revenue - ISNULL(p.Revenue, 0) AS YoY_Change22FROM CurrentYearSales c23LEFT JOIN PreviousYearSales p ON DATEADD(YEAR, -1, c.OrderDate) = p.OrderDate24ORDER BY c.OrderDate;3.3 Business Days Calculation
SQL
1-- Orders on weekdays only2SELECT 3 OrderDate,4 DATENAME(WEEKDAY, OrderDate) AS DayName,5 TotalDue6FROM Sales.SalesOrderHeader7WHERE DATEPART(WEEKDAY, OrderDate) NOT IN (1, 7) -- Exclude Sat/Sun8AND YEAR(OrderDate) = 20139ORDER BY OrderDate;3.4 Rolling 30-Day Analysis
SQL
1-- Orders in last 30 days (from a reference date)2DECLARE @ReferenceDate DATE = '2014-06-30';34SELECT 5 CustomerID,6 COUNT(*) AS OrderCount,7 SUM(TotalDue) AS TotalRevenue8FROM Sales.SalesOrderHeader9WHERE OrderDate BETWEEN DATEADD(DAY, -30, @ReferenceDate) AND @ReferenceDate10GROUP BY CustomerID11ORDER BY TotalRevenue DESC;4. Data Type Conversion
4.1 CAST và CONVERT
SQL
1-- CAST syntax2SELECT 3 CAST(ListPrice AS VARCHAR(20)) AS PriceString,4 CAST('2024-01-15' AS DATE) AS DateValue,5 CAST(123.456 AS INT) AS IntValue6FROM Production.Product7WHERE ProductID = 1;89-- CONVERT with style codes10SELECT 11 OrderDate,12 CONVERT(VARCHAR(10), OrderDate, 101) AS US_Format, -- mm/dd/yyyy13 CONVERT(VARCHAR(10), OrderDate, 103) AS UK_Format, -- dd/mm/yyyy14 CONVERT(VARCHAR(10), OrderDate, 112) AS ISO_Compact, -- yyyymmdd15 CONVERT(VARCHAR(20), OrderDate, 120) AS ISO_Full -- yyyy-mm-dd hh:mi:ss16FROM Sales.SalesOrderHeader17WHERE SalesOrderID = 43659;4.2 TRY_CAST và TRY_CONVERT
SQL
1-- Safe conversion (returns NULL instead of error)2SELECT 3 TRY_CAST('123' AS INT) AS ValidInt,4 TRY_CAST('abc' AS INT) AS InvalidInt,5 TRY_CONVERT(DATE, '2024-01-15') AS ValidDate,6 TRY_CONVERT(DATE, 'not a date') AS InvalidDate;4.3 PARSE và TRY_PARSE
SQL
1-- Parse with culture2SELECT 3 TRY_PARSE('15/01/2024' AS DATE USING 'en-GB') AS UK_Date,4 TRY_PARSE('01/15/2024' AS DATE USING 'en-US') AS US_Date,5 TRY_PARSE('$1,234.56' AS MONEY USING 'en-US') AS US_Money;5. NULL Handling
5.1 ISNULL, COALESCE, NULLIF
SQL
1SELECT 2 ProductID,3 Name,4 Color,5 -- ISNULL: Replace NULL with default6 ISNULL(Color, 'No Color') AS ColorWithDefault,7 8 -- COALESCE: First non-NULL value9 COALESCE(Color, Size, 'Unknown') AS FirstNonNull,10 11 -- NULLIF: Return NULL if equal12 NULLIF(Color, 'Black') AS NotBlack13FROM Production.Product14WHERE ProductSubcategoryID = 1;5.2 NULL in Calculations
SQL
1-- NULL với dates2SELECT 3 SalesOrderID,4 OrderDate,5 ShipDate,6 DATEDIFF(DAY, OrderDate, ISNULL(ShipDate, GETDATE())) AS DaysToShipOrNow7FROM Sales.SalesOrderHeader;6. Thực hành
Exercises
Exercise 1: String Manipulation
SQL
1-- Tạo email từ FirstName và LastName: firstname.lastname@adventure-works.com2-- Hiển thị: FullName, GeneratedEmail34-- YOUR CODE HERE💡 Xem đáp án
SQL
1SELECT 2 FirstName + ' ' + LastName AS FullName,3 LOWER(FirstName) + '.' + LOWER(LastName) + '@adventure-works.com' AS GeneratedEmail4FROM Person.Person5WHERE PersonType = 'EM'6ORDER BY LastName, FirstName;Exercise 2: Date Analysis
SQL
1-- Phân tích orders theo Day of Week2-- Hiển thị: DayName, OrderCount, TotalRevenue34-- YOUR CODE HERE💡 Xem đáp án
SQL
1SELECT 2 DATENAME(WEEKDAY, OrderDate) AS DayName,3 DATEPART(WEEKDAY, OrderDate) AS DayNumber,4 COUNT(*) AS OrderCount,5 SUM(TotalDue) AS TotalRevenue6FROM Sales.SalesOrderHeader7GROUP BY DATENAME(WEEKDAY, OrderDate), DATEPART(WEEKDAY, OrderDate)8ORDER BY DayNumber;Exercise 3: Age Calculation
SQL
1-- Tính tuổi employees (từ BirthDate đến GETDATE())2-- Hiển thị: EmployeeName, BirthDate, Age34-- YOUR CODE HERE💡 Xem đáp án
SQL
1SELECT 2 p.FirstName + ' ' + p.LastName AS EmployeeName,3 e.BirthDate,4 DATEDIFF(YEAR, e.BirthDate, GETDATE()) - 5 CASE 6 WHEN DATEADD(YEAR, DATEDIFF(YEAR, e.BirthDate, GETDATE()), e.BirthDate) > GETDATE()7 THEN 1 8 ELSE 0 9 END AS Age10FROM HumanResources.Employee e11JOIN Person.Person p ON e.BusinessEntityID = p.BusinessEntityID12ORDER BY Age DESC;Exercise 4: Monthly Report Format
SQL
1-- Format monthly sales report2-- Hiển thị: MonthYear (format: 'January 2014'), Revenue (format: $1,234,567.89)34-- YOUR CODE HERE💡 Xem đáp án
SQL
1SELECT 2 FORMAT(OrderDate, 'MMMM yyyy') AS MonthYear,3 FORMAT(SUM(TotalDue), 'C', 'en-US') AS Revenue4FROM Sales.SalesOrderHeader5GROUP BY YEAR(OrderDate), MONTH(OrderDate), FORMAT(OrderDate, 'MMMM yyyy')6ORDER BY YEAR(OrderDate), MONTH(OrderDate);7. Tổng kết
String Functions Quick Reference
| Category | Functions |
|---|---|
| Length/Extract | LEN, DATALENGTH, LEFT, RIGHT, SUBSTRING |
| Modify | UPPER, LOWER, TRIM, REPLACE, STUFF |
| Search | CHARINDEX, PATINDEX |
| Combine | CONCAT, CONCAT_WS, STRING_AGG |
DateTime Functions Quick Reference
| Category | Functions |
|---|---|
| Current | GETDATE, GETUTCDATE, SYSDATETIME |
| Extract | YEAR, MONTH, DAY, DATEPART, DATENAME |
| Calculate | DATEADD, DATEDIFF, EOMONTH |
| Format | FORMAT, CONVERT |
| Construct | DATEFROMPARTS, DATETIME2FROMPARTS |
CONVERT Style Codes (Common)
| Code | Format | Example |
|---|---|---|
| 101 | mm/dd/yyyy | 01/15/2024 |
| 103 | dd/mm/yyyy | 15/01/2024 |
| 112 | yyyymmdd | 20240115 |
| 120 | yyyy-mm-dd hh:mi:ss | 2024-01-15 14:30:00 |
Bài tiếp theo: CASE và Conditional Logic
