sqlserver 20761上課筆記04

  • NULL
  • 條件下在ON 與WHERE的差別
  • FUNCTION
    • STRING
    • DATETIME
  • IFF用法
  • CHOOSE用法
  • 轉型CONVERT AND CAST TRY_PARSE

NULL

空值(Empty)

未知(Unkown)

必要性:Employee table中 leave_date,盤點table actural_qty

3 VALUE LOGICAL

AND T F U (T與F各帶一次)
T T F U
F F F F
U U F U
OR T F U
T T T T
F T F U
U T U U

NOT T = F ,NOT F = T ,NOT U = U

SELECT c1,c2,c3,
c1+c2+c3 AS total
FROM dbo.TestNull

--運算中包含NULL則NULL

SELECT c1,c2,c3,
ISNULL(c1,0) + ISNULL(c2,0) +ISNULL(c3,0) AS total
FROM dbo.TestNull
--使用ISNULL解決

條件下在ON 與WHERE的差別

  • 只對LEFT JOIN、RIGHT JOIN 有差異,INNER JOIN 沒差
  • LEFT JOIN 時ON則過濾右表,WHERE為JOIN後的條件過濾
SELECT c.custid,c.companyname,o.orderid
FROM Sales.Customers c
LEFT JOIN Sales.Orders o
  ON c.custid = o.custid AND c.city='Paris';
--左邊至少出現一次,但右邊只符合city為paris的有值,其他為null

SELECT c.custid,c.companyname,o.orderid
FROM Sales.Customers c
LEFT JOIN Sales.Orders o
  ON c.custid = o.custid
WHERE c.city = 'paris';
--表join完才過濾條件

 Function

numeric

SELECT ROUND(12345.6789,2)--12345.6800
SELECT ROUND(12345.6789,-3)--12000.0000
SELECT ROUND(12345.6789,0,1)--123456.00 無條件捨去

string

--擷取字串
SELECT LEFT('Microsoft sql server sql',9), --Microsoft
SUBSTRING('Microsoft sql server sql',11,3) --sql
,RIGHT('Microsoft sql server',6) --server


--取出比對字串的起始INDEX
SELECT CHARINDEX('SQL', 'Microsoft SQL Server SQL SQL');--11
SELECT CHARINDEX('SQL', 'Microsoft SQL Server SQL SQL',12);--22
SELECT CHARINDEX('SQL', 'Microsoft SQL Server SQL SQL',23);--26
SELECT CHARINDEX('SQL', 'Microsoft SQL Server SQL SQL',27);-- 0


--字串取代
SELECT REPLACE('Learning about T-SQL string functions', 'T-SQL', 'Transact-SQL');


--去除字串空白
SELECT RTRIM('   ABC   '),
LTRIM('   ABC   '),
RTRIM(LTRIM('   ABC   '));


--串接
--SQL2012
SELECT CONCAT(productid, '-', productname, ':', unitprice)
FROM Production.Products;
  • 計算字串長度
    • LEN:計算字串有多少個字元,中英文UNICODE與否,每個字元都是一個會忽略後面空白
    • DATALENGTH:計算字串佔多少Byte
      • 中文x2
      • 英數:unicode x2 ,ANSI x1
      • 不會忽略空白
SELECT LEN('   中文字ABC   '),--9
DATALENGTH('   中文字ABC   '),--15
LEN(N'   中文字ABC   '),--9
DATALENGTH(N'   中文字ABC   ');--24

DateTime

--取得年、月、日
SELECT YEAR('2016-3-16'),MONTH('2016-3-16'),DAY('2016-3-16');

--利用DATEPART取得年、月、日、周、星期幾、時、分、秒,會依設定的語言有所不同
SELECT DATEPART(YEAR, GETDATE()),
DATEPART(MONTH, GETDATE()),
DATEPART(DAY, GETDATE()),
DATEPART(WEEK, GETDATE()),
DATEPART(WEEKDAY, GETDATE()),
DATEPART(HOUR, GETDATE()),
DATEPART(MINUTE, GETDATE()),
DATEPART(SECOND, GETDATE());


--利用DATENAME取得日期NAME
SELECT * FROM sys.syslanguages;
SET LANGUAGE N'繁體中文'
SET LANGUAGE N'us_english'
SELECT DATENAME(YEAR, GETDATE()),
DATENAME(MONTH, GETDATE()),
DATENAME(DAY, GETDATE()),
DATENAME(WEEK, GETDATE()),
DATENAME(WEEKDAY, GETDATE()),
DATENAME(HOUR, GETDATE()),
DATENAME(MINUTE, GETDATE()),
DATENAME(SECOND, GETDATE());


--利用DATEADD取得增加後的單位時間
SELECT DATEADD(YEAR, 10, GETDATE()),
DATEADD(MONTH, 10, GETDATE()),
DATEADD(WEEK, 10, GETDATE()),
DATEADD(DAY, 10, GETDATE()),
DATEADD(HOUR, 10, GETDATE()),
DATEADD(MINUTE, 10, GETDATE()),
DATEADD(SECOND, 10, GETDATE());


--利用DATEDIFF取得時間單位差值
SELECT DATEDIFF(YEAR, '2017-12-31', '2018-1-1'),
DATEDIFF(MONTH, '2017-12-31', '2018-1-1'),
DATEDIFF(DAY, '2017-12-31', '2018-1-1'),
DATEDIFF(HOUR, '2017-12-31', '2018-1-1'),
DATEDIFF(MINUTE, '2017-12-31', '2018-1-1'),
DATEDIFF(SECOND, '2017-12-31', '2018-1-1');


--取得月底最後一天
SELECT EOMONTH(GETDATE()),
EOMONTH(GETDATE(), 1),--2019-12-31
EOMONTH(GETDATE(), 2),--2020-01-31
EOMONTH(GETDATE(), 3),--2020-02-29
EOMONTH(GETDATE(), -1),--2019-11-30
EOMONTH(GETDATE(), -2),--2019-10-31
EOMONTH(GETDATE(), -3);--2019-09-30


--組合時間
SELECT DATETIMEFROMPARTS(2016, 3, 16, 12, 30, 0, 0),
DATETIME2FROMPARTS(2016, 3, 16, 12, 30, 0, 0, 0),
DATEFROMPARTS(2016, 3, 16),
TIMEFROMPARTS(12, 30, 0, 0, 0 );

資料轉型

  • CONVERT:CONVERT為SQL SERVER專有,標準的ANSI為CAST,但由於格式化回傳的附加功能所以還是有可能用到
  • CAST
--CONVERT 轉型
SELECT CONVERT(varchar(10), productid) + '-' + productname + ':' + CONVERT(varchar(10), unitprice)
FROM Production.Products;

--CONCERT 格式轉換
SELECT CONVERT(varchar(20), GETDATE(), 111);
SELECT CONVERT(varchar(20), GETDATE(), 112);

SELECT CONVERT(varchar(20), GETDATE(), 11);
SELECT CONVERT(varchar(20), GETDATE(), 12);

--CAST 轉型
SELECT CAST('2016-2-31' AS date)

--TRY_PARSE轉型 失敗時會給NULL
SELECT TRY_PARSE('2016-2-31' AS date)--NULL
SELECT TRY_PARSE('2016-2-12' AS date)--201602-12

SELECT phone, TRY_PARSE(RIGHT(phone,4) AS int)
FROM Sales.Customers;

FORMAT

SELECT FORMAT(12345.6789, 'c', 'en-us'),
FORMAT(12345.6789, 'c', 'zh-tw'),
FORMAT(12345.6789, 'c', 'ja-jp'),
FORMAT(12345.6789, 'c', 'de-de'),
FORMAT(12345.6789, '#,##0.00');

SELECT FORMAT(GETDATE(), 'd', 'en-us'),
FORMAT(GETDATE(), 'd', 'zh-tw'),
FORMAT(GETDATE(), 'd', 'ja-jp'),
FORMAT(GETDATE(), 'd', 'en-gb');

SELECT FORMAT(GETDATE(), 'yyyy-MM-dd MMM MMMM ddd dddd', 'en-us'),
FORMAT(GETDATE(), 'yyyy-MM-dd MMM MMMM ddd dddd', 'ja-jp'),
FORMAT(GETDATE(), 'yyyy-MM-dd MMM MMMM ddd dddd', 'zh-tw'),
FORMAT(GETDATE(), 'yyyy-MM-dd MMM MMMM ddd dddd', 'de-de');

IFF

SELECT productid, productname, unitprice, 
IIF(unitprice >= 20, N'高價位',
	IIF(unitprice >=10, N'中價位',	
		IIF(unitprice < 10, N'低價位', N'未知'))) AS pricetype
FROM Production.Products;

CHOOSE

需配合資料庫的設計

SELECT productid, productname, unitprice, 
IIF(unitprice >= 20, N'高價位',
	IIF(unitprice >=10, N'中價位',	
		IIF(unitprice < 10, N'低價位', N'未知'))) AS pricetype
FROM Production.Products;

boolean function

SELECT ISDATE('2016-2-31')
SELECT ISDATE('2016-2-12')
SELECT ISDATE(NULL)

SELECT ISNUMERIC('123');
SELECT ISNUMERIC('abc');
SELECT ISNUMERIC(null);