---
# System prepended metadata

title: SQL
tags: [D-CODE]

---

###### tags: `D-CODE`

# SQL

---

:::info
[ Isolation Levels](https://totoroliu.medium.com/%E8%B3%87%E6%96%99%E5%BA%AB-isolation-levels-c587d3103ba4)

* SQL null無法比對運算，因此要用ISNULL把值改為空白後方能比對

:::

---

:::spoiler 常用
```
	RIGHT('00000000' + CAST(t.pat_no AS varchar), 8)	
	(CAST(FORMAT(DATEADD(YEAR,-1911,  CAST(a.enc_time AS date)), N'yyyMM') AS int)
	CAST(STR(SUBSTRING(a.his_opd_no, 1, 7) + 19110000) AS date)  AS ODR_RO_DATE
```

:::

---

:::spoiler ROWS BETWEEN
以「視窗框架」：ROWS BETWEEN 2 PRECEDING AND CURRENT ROW為例，這是指定一個視窗，此視窗是從目前資料列前面的第二個資料列作為起始點，而以目前資料列作為結束點，此視窗函數可以操作的資料列視窗大小為三筆資料列。
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW：此為預設值，這是指定一個視窗，此視窗從資料分割的第一個資料列作為起始點，而以資料分割的目前資料列作為結束點。
RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING：這是指定一個視窗，此視窗從資料分割的目前資料列作為起始點，而以資料分割的最後一個資料列作為結束點。
ROWS BETWEEN 2 FOLLOWING AND 10 FOLLOWING：這是指定一個視窗，此視窗是從目前資料列後面的第二個資料列作為起始點，而以目前資料列後面的第十個資料列作為結束點。
:::

---

:::spoiler UNPIVOT

![](https://i.imgur.com/wMM1OMC.png)

```
SELECT *
    FROM
        (
          Select GroupCol,col2,col3,col4........ FROM SourceTable
          -- 3.1 欲進行反轉置的資料來源
        ) AS p
    UNPIVOT
        (
          ValueCol FOR unPivotCol IN (col2,col3,col4.........) -- ㄧ定要不包含群組欄位
          -- 3.2 ValueCol 和 unPivotCol 為使用者自行命名的欄位名稱
          -- 3.3 ValueCol 的資料為資料列（Row）資料轉成資料行（Column）資料（非群組欄位轉為ValueCol）
          -- 3.4 unPivotCol 的資料為 col2欄位資料、col3欄位資料、col4欄位資料........
        ) AS pv  
        
      
SELECT *
    FROM
        (
          Select Employee,事假,病假,公假,陪產假 FROM #UNPIVOT
        ) AS p
    UNPIVOT
        (
          Hours FOR Kind IN (事假,病假,公假,陪產假)
        ) AS pv

-- OR

SELECT *
    FROM #UNPIVOT AS p
    UNPIVOT
        (
          Hours FOR Kind IN (事假,病假,公假,陪產假)
        ) AS pv

-- AAAAA的陪產假為NULL，UNPIVOT後，AAAAA的假別就不會有陪產假
```
:::

---
:::spoiler TRY CATCH
BEGIN TRY
  BEGIN TRANSACTION
   IF @@ERROR = 0

   --沒問題就確認交易完成，資料也會在這時候確認新增和修改
    COMMIT TRANSACTION
   ELSE
   --若是有問題就取消交易，讓資料不被這三段T-SQL所影響
    ROLLBACK TRANSACTION

  END TRY

BEGIN CATCH

END CATCH
:::

---

:::spoiler ALTER
alter TABLE [dbo].[tableName] ALTER COLUMN [FiledName] [nvarchar](40) 
:::
 
---

:::spoiler 查詢主KEY
select  From INFORMATION_SCHEMA.KEY_COLUMN_USAGE

:::

---

:::spoiler 欄位合併
SELECT ProductId,
    (
        SELECT ',' + PO_A.[Owner]
        FROM ProductOwner PO_A
        WHERE PO_A.ProductId = PO_B.ProductId
        FOR XML PATH('')
        ) AS Owners
FROM ProductOwner PO_B
:::

---

:::spoiler 找出重覆資料
SELECT * FROM table

GROUP BY id

HAVING count(*)>1
:::

---

:::spoiler PATINDEX
SELECT  *
FROM TBDEP a
ORDER BY CASE WHEN PATINDEX( '%(舊)%' ,depname) > 0 THEN depno ELSE '' END
:::

---
:::spoiler CTE 日期
WITH mycte AS
(
	SELECT CAST('1900-01-01' AS DATETIME) DateValue
	UNION ALL
	SELECT DateValue + 1
	FROM mycte
	WHERE DateValue + 1 < '2050-12-31'
)
SELECT DateValue
FROM mycte
OPTION (MAXRECURSION 0)
:::

---

:::spoiler PIVOT

DECLARE @Year nvarchar(40) = '106';
DECLARE @Semester nvarchar(40) ='1';
DECLARE @DayfgID nvarchar(5) ='1';

--select isnull(a.Vaild,0) Vaild,COUNT(1) Amt
--from tVoteTeCategoryUsers a
--join tVoteTeAnswers b
--on a.TeCategoryID=b.TeCategoryID
--and a.StudentID=b.StudentID
--join tVoteTeCategory c
--on a.TeCategoryID=c.TeCategoryID
--where c.ACADYear = @Year and c.Semester = @Semester
--group by isnull(a.Vaild,0)

SELECT [0] inVaild,[1] Vaild
FROM (
	select isnull(a.Vaild,0) Vaild
	from tVoteTeCategoryUsers a
	join tVoteTeAnswers b
	on a.TeCategoryID=b.TeCategoryID
	and a.StudentID=b.StudentID
	join tVoteTeCategory c
	on a.TeCategoryID=c.TeCategoryID
	where c.ACADYear = @Year and c.Semester = @Semester
	) as GroupTable
PIVOT
(
	count(Vaild)
	FOR Vaild IN ([0], [1])
) AS PivotTable


--https://blog.xuite.net/f8789/DCLoveEP/30800686-SQL+-+%E4%BD%BF%E7%94%A8+PIVOT
 SELECT 
	*
FROM (
		SELECT  	
			 
				 a.fundsno3, --學校配合款
				 a.years,    
 			     SUM(a.smoney)   AS smoney,
                 SUM(a.appmoney) AS appmoney_核定前金額,    --核定前金額,
				 (
					SELECT SUM(smoney) 
					FROM ITSCHOOLDEPBUDGET
					WHERE fundsno3 = a.fundsno3 AND  						 				 
						  years = '109'		
				 		 			  
				 ) AS AA,
				 (
					SELECT SUM(smoney) 
					FROM ITSCHOOLDEPBUDGET
					WHERE fundsno3 = a.fundsno3 AND 						  					 
						  years = '110'						 		 			  
				 ) AS BB	 
		FROM ITSCHOOLDEPBUDGET a --預算明細檔
						INNER JOIN TBREFCODE b  --系統代碼檔
									ON b.refcodeno = 'budfunds' AND b.refcode = a.fundsno3
						INNER JOIN  (
									   SELECT depno,
											  CASE WHEN ISNULL(upper,'') = '0000' 
															THEN depno 
															ELSE upper 
											  END AS upper 
									   FROM TBDEP --學校部門表
									 ) c 
									ON c.depno = a.depno
		WHERE LEFT(a.budsubno,1) = '4'   AND --預算科目
			  LEFT(a.fundsno3,1) <> 'P'  AND --學校配合款
			  a.years BETWEEN '109' AND '110' AND
			  a.fundsno3 = '419200'
		GROUP BY b.upper,a.fundsno3,b.refname,c.upper,a.years 
		--ORDER BY b.upper,a.fundsno3,b.refname,c.upper,a.years
) t 
PIVOT (
	-- 設定彙總欄位及方式
	 MAX(years)  
	-- 設定轉置欄位，並指定轉置欄位中需彙總的條件值作為新欄位
	FOR years IN ( [109], [110])
) p;
:::



---

:::spoiler STRING_SPLIT
			 
SELECT b.inno, b.money,b.indate, *
FROM TBPENNY_DETIAL a --收款收據-收款收據明細資料表
						LEFT JOIN TBINDETAIL b --收入相關-收入明細資料表
							ON a.doc_id IN  (
												SELECT value  
												FROM  STRING_SPLIT(b.pennyautoid, ',')														  				
											)
WHERE a.pennyno = '111600-11002220002'


2014版寫法


SELECT Split.a.value('.', 'NVARCHAR(MAX)') AS Value 
	FROM (	 
			SELECT CAST ('<M>' + REPLACE(CAST (nid_rec AS nvarchar(MAX)) , ',', '</M><M>') + '</M>' AS XML) AS Data
			FROM hg_mnid
			WHERE nid_id = '06BC'
			  AND nid_code IN ('011')
　			       
	) AS A 
			CROSS APPLY Data.nodes ('/M') AS Split(a)
:::


---

:::spoiler 一對多筆資料
 
```

WITH CTE_ITFORM
             AS (
                    SELECT  formno,
                            wruserno,
                            wrusername,
                            depno,
                            (
                                SELECT depname
                                FROM TBDEP
                                WHERE TBDEP.depno = ITFORM.depno
                            ) AS depname,
                            CASE
                              WHEN isbt = 'purchase' THEN '請購'
                              WHEN isbt = 'normal'   THEN '借支'
                            END AS isbt,
                            casename,
                            (
                                SELECT TOP 1 budno + ',' + (
                                                            SELECT budname
                                                            FROM ITSCHOOLDEPBUDGET
                                                            WHERE budno = ITFORM_DETIAL.budno
                                                            )
                                FROM ITFORM_DETIAL
                                WHERE formno = ITFORM.formno
                            ) AS budno,
                            (
                                SELECT SUM(bmoney)
                                FROM ITFORM_DETIAL
                                WHERE ITFORM_DETIAL.formno = ITFORM.formno
                            ) AS bmoney
                    FROM ITFORM
                    WHERE   kind = '1'  AND
            status >= 1 AND
            status < 9  AND
            EXISTS (
                     SELECT 1
                     FROM ITFORM_DETIAL
                            INNER JOIN ITSCHOOLDEPBUDGET
                                        ON ITSCHOOLDEPBUDGET.budno = ITFORM_DETIAL.budno
                            INNER JOIN ITSCHOOLDEP
                                        ON ITSCHOOLDEP.planno = ITSCHOOLDEPBUDGET.planno
                     WHERE (
                              ITSCHOOLDEP.edate = CONVERT(VARCHAR,CAST(YEAR(GETDATE()) AS NVARCHAR) + '-06' + '-01',111) OR
                              ITSCHOOLDEP.edate = CONVERT(VARCHAR,CAST(YEAR(GETDATE()) AS NVARCHAR) + '-12' + '-01',111)
                           )
                   )


                ),

                  CET_WRUSERNO
            AS (
                    SELECT wruserno
                    FROM ITFORM
                    WHERE   kind = '1'  AND
            status >= 1 AND
            status < 9  AND
            EXISTS (
                     SELECT 1
                     FROM ITFORM_DETIAL
                            INNER JOIN ITSCHOOLDEPBUDGET
                                        ON ITSCHOOLDEPBUDGET.budno = ITFORM_DETIAL.budno
                            INNER JOIN ITSCHOOLDEP
                                        ON ITSCHOOLDEP.planno = ITSCHOOLDEPBUDGET.planno
                     WHERE (
                              ITSCHOOLDEP.edate = CONVERT(VARCHAR,CAST(YEAR(GETDATE()) AS NVARCHAR) + '-06' + '-01',111) OR
                              ITSCHOOLDEP.edate = CONVERT(VARCHAR,CAST(YEAR(GETDATE()) AS NVARCHAR) + '-12' + '-01',111)
                           )
                   )
                    GROUP BY wruserno
               )


            SELECT wruserno,
                   (
                        SELECT  b.formno    + ':' +
                                b.isbt      + ':' +
                                b.casename  + ':' +
                                b.budno     + ':' +
                                CAST ( b.bmoney AS Varchar )  + ';'
                        FROM CTE_ITFORM b
                        WHERE b.wruserno = a.wruserno
                        FOR XML PATH('')
                   ) AS formno
            FROM CET_WRUSERNO a
            UNION
            SELECT 'ACC' AS wruserno,
                   (
                        SELECT  b.formno    + ':' +
                                b.isbt      + ':' +
                                b.casename  + ':' +
                                b.budno     + ':' +
                                CAST ( b.bmoney AS Varchar )  + ':' +
                                b.depname     + ':' +
                                b.wrusername + ';'
                        FROM CTE_ITFORM b
                        FOR XML PATH('')
                   ) AS formno
            FROM CTE_ITFORM b
```
 
:::


---

:::spoiler 抓小數點後幾位數

	SELECT MONEY,*
	FROM ITFORM_BUYACT
	WHERE PARSENAME(MONEY, 1)  > 0
:::

---

:::spoiler 往前抓到有資料為止
 select bankno,sdate,remark 
 from TBINOUTDAY 
 where sdate = (
				 SELECT TOP 1 h.sdate
				 FROM (
						SELECT  a.sdate  AS sdate				 
						FROM TBINOUTDAY a
						WHERE a.remark is not null AND a.sdate <= '2020-11-30'
						GROUP BY a.sdate 
					  ) h
				 ORDER BY h.sdate DESC
				)
 order by bankno DESC
:::

---
:::spoiler 指標
CREATE TABLE [#Table_name]
(
   COLUMN_NAME nvarchar(100)
)

INSERT INTO #Table_name (COLUMN_NAME)
SELECT a.COLUMN_NAME  
FROM (		
	SELECT b.COLUMN_NAME 
	FROM    INFORMATION_SCHEMA.TABLES a
	LEFT JOIN INFORMATION_SCHEMA.COLUMNS b ON a.TABLE_NAME=b.TABLE_NAME 
	WHERE   TABLE_TYPE='BASE TABLE' 
			AND a.Table_name IN (
						'tSteBuy' 				 
						 ) --輸入想要的表格名稱
	 
) a

--1.不回傳受影響的資料列(可節省網路傳輸),通常如果沒有要看的話,會寫不回傳,又能節省網路傳輸)
--2.雖然不回傳,但不影響@@ROWCOUNT,所以如果想知道影響的資料列,還是能用@@ROWCOUNT來讀取
SET NOCOUNT ON

DECLARE @COLUMN_NAME NVARCHAR(MAX)

--宣告資料指標內容
DECLARE MYCURSOR CURSOR FOR
(
    SELECT COLUMN_NAME FROM #Table_name
)
--開啟資料指標
OPEN MYCURSOR
--取得資料指標內第一筆資料
FETCH NEXT FROM MYCURSOR INTO @COLUMN_NAME 
--當成功取的資料進入處理程序
WHILE @@FETCH_STATUS = 0
BEGIN	  
 
    ----資料處理區----  
	-- 找出哪些欄位比較常用(超過原始資料筆數的70%)
	DECLARE @query NVARCHAR(MAX) = N'
									   SELECT  '''  + @COLUMN_NAME + ''', '+ 'COUNT(' + @COLUMN_NAME + ')
									   FROM tSteBuy
									   WHERE ISNULL(CONVERT(varchar,' + @COLUMN_NAME + '),' + '''' +                   '''' + ') <> ''''
									   HAVING  COUNT(' + @COLUMN_NAME + ')  >							 (SELECT COUNT(formno) FROM			  tSteBuy) * 0.7
									    
								'
	--SELECT @query  
    EXECUTE sp_executesql    @query  	  
	--SELECT   @COLUMN_NAME  ,   @COLUMN_NAME 
	--FROM ITFORM   
	--WHERE ISNULL(@COLUMN_NAME, '') <> ''
 
    ------------------
    --取得下一筆資料
    FETCH NEXT FROM MYCURSOR INTO @COLUMN_NAME 
END



--關閉資料指標
CLOSE MYCURSOR

 
--移除資料指標參考
DEALLOCATE MYCURSOR 

 --移除暫存表
DROP TABLE #Table_name

:::


---

:::spoiler usp_Del
CREATE PROCEDURE usp_Del_Products
	@ProdctID    int	
AS
BEGIN
	SET NOCOUNT ON;

	DECLARE @count int
	  
	SET @count = (SELECT count(*) FROM [dbo].[Products] WHERE ProdctID = @ProdctID)

	IF @count > 0
	 BEGIN  
	   BEGIN TRY	
			BEGIN TRANSACTION

			DELETE FROM Products WHERE ProdctID = @ProdctID;

			IF @@ERROR = 0
			 BEGIN
				commit transaction;--確認交易
			 END 
			ELSE
			 BEGIN
				rollback transaction;--回復交易
			 END
	   END TRY
	   BEGIN CATCH
	     --DB查詢用
		 SELECT ERROR_NUMBER() AS ErrorNumber,
			    ERROR_MESSAGE() AS ErrorMessage,
			    ERROR_LINE() AS ErrorLine,
			    ERROR_PROCEDURE() AS ErrorProcedure,
			    ERROR_SEVERITY() AS ErrorSeverity,
			    ERROR_STATE() AS ErrorState

	     --系統拋回訊息用
		 DECLARE @ErrorMessage As VARCHAR(1000) = CHAR(10)+'錯誤代碼：' +CAST(ERROR_NUMBER() AS VARCHAR)
												 +CHAR(10)+'錯誤訊息：'+	ERROR_MESSAGE()
												 +CHAR(10)+'錯誤行號：'+	CAST(ERROR_LINE() AS VARCHAR)
												 +CHAR(10)+'錯誤程序名稱：'+	ISNULL(ERROR_PROCEDURE(),'')
		 DECLARE @ErrorSeverity As Numeric = ERROR_SEVERITY()
		 DECLARE @ErrorState As Numeric = ERROR_STATE()
		 RAISERROR( @ErrorMessage, @ErrorSeverity, @ErrorState);--回傳錯誤資訊
	   END CATCH
	 END
END
:::

---

:::spoiler MERGE
MERGE 語法是 SQL Server 2008 的新語法，可根據與來源資料表聯結的結果，在目標資料表上執行插入、更新或刪除作業。以下就來以範例的方式來實作...

Code：

--建立新資料表名為 大倉庫
Create Table 大倉庫
(
 品名 nvarchar(50),
 庫存量 integer
);

--新增大倉庫資料表資料
Insert into 大倉庫
Values('中文書', 10),('英文書', 5),('法文書', 1);

--建立新資料表名為 進退貨倉庫
Create Table 進退貨倉庫
(
 品名 nvarchar(50),
 進退貨量 integer
);

--新增進退貨倉庫資料表資料
Insert into 進退貨倉庫
Values('中文書', 5),('英文書', -5),('日文書', 6);

--查詢 大倉庫 與 進退貨倉庫 兩資料表的資料
Select * From dbo.大倉庫
Select * From dbo.進退貨倉庫

--將兩張表 MERGE
--當兩張表有資料 MERGE 時，且 庫存量 加上 進退貨量 等於零時，則刪除資料
--當兩張表有資料 MERGE 時，將 庫存量 加上 進退貨量 更新到 庫存量
--當兩張表沒有資料 MERGE 時，將 進退貨倉庫 的資料新增到 大倉庫 中
MERGE INTO 大倉庫
   USING 進退貨倉庫
   ON 大倉庫.品名 = 進退貨倉庫.品名
WHEN MATCHED AND (大倉庫.庫存量 + 進退貨倉庫.進退貨量 = 0) THEN
   DELETE
WHEN MATCHED THEN
   UPDATE SET 大倉庫.庫存量 = 大倉庫.庫存量 + 進退貨倉庫.進退貨量
WHEN NOT MATCHED THEN
   INSERT VALUES(進退貨倉庫.品名, 進退貨倉庫.進退貨量);

--查詢 MERGE 後的結果
Select * From dbo.大倉庫
Select * From dbo.進退貨倉庫
:::

---

:::spoiler ASP.NET BeginTransaction
```
using (ACAD_NPUSTEntities pubkind = new ACAD_NPUSTEntities())
                    {
                        using (ACAD_NPUSTEntities pubcod = new ACAD_NPUSTEntities())
                        {
                            using (var pubkindTs = pubkind.Database.BeginTransaction())
                            {
                                using (var pubcodTs = pubcod.Database.BeginTransaction())
                                {
                                    pubkind.pubkind.Add(m);
                                    pubkind.Configuration.ValidateOnSaveEnabled = false;
                                    //pubkind.SaveChanges();

                                    for (int i = 0; i < n; i++)
                                    {
                                        var r = new pubcod();
                                        //r.codekind = m.codekind;
                                        //r.code = Request["dt_code[]"].Split(',')[i];
                                        //r.codsc = Request["dt_codsc[]"].Split(',')[i];
                                        //r.ecodsc = Request["dt_ecodsc[]"].Split(',')[i];
                                        //r.status = Request["dt_status[]"].Split(',')[i];
                                        //r.updat_date = DateTime.Now;
                                        //r.user_id = getUserAuthInfo().id ?? null;
                                        //r.updat_time = m.updat_date.Value.ToString("HHmmss");
                                        pubcod.pubcod.Add(r);
                                        //pubcod.SaveChanges();
                                    }

                                    try
                                    {
                                        pubkind.SaveChanges();
                                        pubcod.SaveChanges();

                                        pubkindTs.Commit();
                                        pubcodTs.Commit();

                                    }
                                    catch (Exception)
                                    {
                                        pubkindTs.Rollback();
                                        pubcodTs.Rollback();
                                        TempData["CommMsg"] = "新增作業失敗 !";
                                        return View();
                                    }
                                }
                            }
                        }
                    }
                }
```
:::

---

:::spoiler TRANSACTION
```
DECLARE @count int
	  
	SET @count = (SELECT count(*) FROM [dbo].[Products] WHERE ProdctID = @ProdctID)

	IF @count > 0
	 BEGIN  
	   BEGIN TRY	
			BEGIN TRANSACTION

			DELETE FROM Products WHERE ProdctID = @ProdctID;

			IF @@ERROR = 0
			 BEGIN
				commit transaction;--確認交易
			 END 
			ELSE
			 BEGIN
				rollback transaction;--回復交易
			 END
	   END TRY
	   BEGIN CATCH
	     --DB查詢用
		 SELECT ERROR_NUMBER() AS ErrorNumber,
			    ERROR_MESSAGE() AS ErrorMessage,
			    ERROR_LINE() AS ErrorLine,
			    ERROR_PROCEDURE() AS ErrorProcedure,
			    ERROR_SEVERITY() AS ErrorSeverity,
			    ERROR_STATE() AS ErrorState

	     --系統拋回訊息用
		 DECLARE @ErrorMessage As VARCHAR(1000) = CHAR(10)+'錯誤代碼：' +CAST(ERROR_NUMBER() AS VARCHAR)
												 +CHAR(10)+'錯誤訊息：'+	ERROR_MESSAGE()
												 +CHAR(10)+'錯誤行號：'+	CAST(ERROR_LINE() AS VARCHAR)
												 +CHAR(10)+'錯誤程序名稱：'+	ISNULL(ERROR_PROCEDURE(),'')
		 DECLARE @ErrorSeverity As Numeric = ERROR_SEVERITY()
		 DECLARE @ErrorState As Numeric = ERROR_STATE()
		 RAISERROR( @ErrorMessage, @ErrorSeverity, @ErrorState);--回傳錯誤資訊
	   END CATCH
	 END
```
:::


---
:::spoiler STRING_AGG 資料集組成字串的串接功能
```資料集組成字串的串接功能
SELECT
	STRING_AGG(name, ',')
FROM F1Driver
```
:::

---
:::spoiler 流水號
``` 
select RIGHT(REPLICATE('0', 6) + CAST(ISNULL(MAX(CAST(CourseNo AS INT)),0)+1 AS varchar) , 6) AS CourseNo
```

:::

---

:::spoiler SQL Function
```
USE [Test_NCYU_DEV]
GO
/****** Object:  UserDefinedFunction [dbo].[getPubcod]    Script Date: 2022/6/23 上午 08:36:18 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

-- 建立 FUNCTION
/*
08:班級
*/
ALTER FUNCTION [dbo].[getPubcod](@codekind varchar(5), @code varchar(5), @pattern varchar(1)) 
RETURNS varchar(1000)  -- 500若不夠，請加大 
BEGIN
    DECLARE @string varchar(1000)  -- 500若不夠，請加大 
    SET @string = ''

	IF @pattern = '1'
		BEGIN
			 SELECT @string = @string + code + '-' + codsc + ','
			 FROM pubcod
			 WHERE codekind = @codekind AND code = @code
		END
	ELSE
		BEGIN
			 SELECT @string = @string + codsc + ','
			 FROM pubcod
			 WHERE codekind = @codekind AND code = @code
		END
 
	IF LEN(@string) > 1   
	BEGIN
		SET @string = LEFT(@string, LEN(@string) - 1 ) -- 把最後面的逗號後刪除
	END
 
    RETURN @string
END

```

:::

---

:::spoiler 暫存表
```

----增加索引 >> 已有執行
--USE [Test_NCYU_DEV]
--GO
--CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
--ON [dbo].[selstch] ([syear],[sem])
--INCLUDE ([stuno],[deptno],[seqno],[cono],[seldomain],[credit])


-- 清除暫存表
IF object_id('tempdb..#crsopenf_CTE') IS NOT NULL DROP TABLE #crsopenf_CTE;


--學生選課資料(暫存表)
SELECT DISTINCT
	b.syear   	   			, b.sem                 , a.acadno, c.colno
	, a.deptno AS sut_deptno, a.secno               , e.secnam, a.grade
	, a.clacod              , a.stuno               , d.cname , b.deptno
	, b.seqno               , b.attdepno            , b.att_y , b.att_cls
	, b.att_grou            , f.seldomain           , f.cono  , f.credit
	, b.termnum             , b.credit AS crs_credit, b.smn	
INTO #crsopenf_CTE
FROM stufile a
INNER JOIN selstch f ON a.stuno = f.stuno
INNER JOIN crsopenf b ON f.syear = b.syear AND f.sem = b.sem AND f.deptno = b.deptno AND f.seqno = b.seqno
INNER JOIN pubdep c ON a.deptno = c.deptno
INNER JOIN sclperson d ON a.idno = d.idno
INNER JOIN pubsec e ON a.deptno = e.deptno AND a.secno = e.secno
WHERE b.actcd <> '1' AND b.domainno NOT IN ('0001', '0002', '0000') AND f.syear = '110' AND f.sem = '1' 
--AND a.stuno = '1100404' 
	

--上課時間
;WITH crstime_CTE AS (
	SELECT
　	  crstime.syear,
	  crstime.sem,
	  clweek,
	  bcl,
	  ecl,
	  crstime.deptno,
	  crstime.seqno 
	FROM crstime,
	     #crsopenf_CTE
	WHERE crstime.syear = #crsopenf_CTE.syear
　	  AND crstime.sem =  #crsopenf_CTE.sem
　	  AND crstime.deptno = #crsopenf_CTE.deptno
	  AND crstime.seqno = #crsopenf_CTE.seqno
),
-- 將上課時間拆成星期一到星期日，並將節次的資料整合在一格內
week_all AS (
	SELECT DISTINCT 
				(
					 SELECT DISTINCT b.bcl + '-' + b.ecl + ','
					 FROM crstime_CTE b 
					 WHERE a.syear = b.syear AND a.sem = b.sem AND a.deptno = b.deptno AND a.seqno = b.seqno AND a.clweek = b.clweek 
					 FOR XML PATH('')
				) AS t_t,			 
				a.syear,
				a.sem,
				a.deptno,
				a.seqno, 
				a.clweek
	FROM crstime_CTE a
)
 
SELECT  a.syear,
		a.sem,
		a.acadno,
		a.colno,
		a.sut_deptno,
		a.secno,
		a.secnam,
		a.grade,
		a.clacod,
		a.stuno,
		a.cname,
		a.deptno,
		a.seqno,
		a.attdepno,
		a.att_y,
		a.att_cls,
		a.att_grou,
		a.seldomain,
		a.cono,
		a.credit,
		a.termnum,
		a.crs_credit,
		a.smn,
	    week_1.t_t AS t_t1,
		week_2.t_t AS t_t2,
		week_3.t_t AS t_t3,
		week_4.t_t AS t_t4,
		week_5.t_t AS t_t5,
		week_6.t_t AS t_t6,
		week_7.t_t AS t_t7		 
FROM #crsopenf_CTE a
LEFT JOIN (SELECT * FROM week_all a WHERE a.clweek = 1) AS week_1 ON a.syear = week_1.syear AND a.sem = week_1.sem AND a.deptno = week_1.deptno AND a.seqno = week_1.seqno
LEFT JOIN (SELECT * FROM week_all a WHERE a.clweek = 2) AS week_2 ON a.syear = week_2.syear AND a.sem = week_2.sem AND a.deptno = week_2.deptno AND a.seqno = week_2.seqno
LEFT JOIN (SELECT * FROM week_all a WHERE a.clweek = 3) AS week_3 ON a.syear = week_3.syear AND a.sem = week_3.sem AND a.deptno = week_3.deptno AND a.seqno = week_3.seqno
LEFT JOIN (SELECT * FROM week_all a WHERE a.clweek = 4) AS week_4 ON a.syear = week_4.syear AND a.sem = week_4.sem AND a.deptno = week_4.deptno AND a.seqno = week_4.seqno
LEFT JOIN (SELECT * FROM week_all a WHERE a.clweek = 5) AS week_5 ON a.syear = week_5.syear AND a.sem = week_5.sem AND a.deptno = week_5.deptno AND a.seqno = week_5.seqno
LEFT JOIN (SELECT * FROM week_all a WHERE a.clweek = 6) AS week_6 ON a.syear = week_6.syear AND a.sem = week_6.sem AND a.deptno = week_6.deptno AND a.seqno = week_6.seqno
LEFT JOIN (SELECT * FROM week_all a WHERE a.clweek = 7) AS week_7 ON a.syear = week_7.syear AND a.sem = week_7.sem AND a.deptno = week_7.deptno AND a.seqno = week_7.seqno
--WHERE a.syear = '110' 
--  AND a.sem = '1'
--  AND a.deptno = '151'
--  AND a.seqno = '0014'
```
:::

---

:::spoiler CUBE
[CUBE](https://www.mssqltips.com/sqlservertip/6315/group-by-in-sql-server-with-cube-rollup-and-grouping-sets-examples/)
:::

---

:::spoiler CTE + PIVOT
```
--查詢學生選課的教室及上課時間
--學生選課資料
WITH crsopenf_cte AS ( 
    
	SELECT DISTINCT  
			  b.syear,
			  b.sem,
			  a.acadno,
			  c.colno,
			  a.deptno AS sut_deptno,
			  a.secno,
			  e.secnam,
			  a.grade,
			  a.clacod,
			  a.stuno,
			  d.cname,
			  b.deptno,
			  b.seqno,
			  b.attdepno,
			  b.att_y,
			  b.att_cls,
			  b.att_grou,
			  f.seldomain,
			  f.cono,
			  f.credit,
			  b.termnum,
			  b.credit AS crs_credit,
			  b.smn	
	FROM stufile a,
		 crsopenf b,
		 pubdep c,
		 sclperson d,
		 selstch f,
		 pubsec e
	WHERE a.deptno = e.deptno
	AND a.secno = e.secno
	AND a.deptno = c.deptno
	AND a.idno = d.idno
	AND a.stuno = f.stuno
	AND f.syear = b.syear
	AND f.sem = b.sem
	AND f.deptno = b.deptno
	AND f.seqno = b.seqno
	AND f.syear = '110'
	AND f.sem = '1'
    --AND a.stuno = '1100404'
	AND b.actcd <> '1'
	AND b.domainno NOT IN ('0001', '0002', '0000')

),--上課教室
 class_room_cte AS (
	
    SELECT crsbu.buna,
		   crstime.roomno,
		   crstime.syear,
		   crstime.sem,
		   crstime.deptno,
		   crstime.seqno
    FROM crstime,
         crsbu 
    WHERE crsbu.buno=crstime.buno
      AND crsbu.areano=crstime.areano
)
--上課時間
, crstime_cte AS (

	SELECT
　	  crstime.syear,
	  crstime.sem,  
	  clweek,
	  bcl,
	  ecl,
	  crstime.deptno,
	  crstime.seqno
	FROM crstime 
 
) 
 

SELECT 
	   p.syear,
	   p.sem,
	   p.acadno,
	   p.colno,
	   p.sut_deptno,
	   p.secno,
	   p.secnam,
	   p.grade,
	   p.clacod,
	   p.stuno,
	   p.cname,
	   p.deptno,
	   p.seqno,
	   p.attdepno,
	   p.att_y,
	   p.att_cls,
	   p.att_grou,
	   p.seldomain,
	   p.cono,
	   p.credit,
	   p.smn,
	   (
			SELECT DISTINCT b.buna + '-' + roomno + ',' 
			FROM class_room_cte b
			WHERE p.syear = b.syear AND p.sem = b.sem AND p.deptno = b.deptno AND p.seqno = b.seqno	 
			FOR XML PATH('')
	   ) AS room, --教室
	   p.[1], --星期1
	   p.[2], --星期2
	   p.[3], --星期3
	   p.[4], --星期4
	   p.[5], --星期5
	   p.[6], --星期6
	   p.[7]  --星期7	 
FROM ( 
	SELECT  a.syear,
			a.sem,
			a.acadno,
			a.colno,
			a.sut_deptno,
			a.secno,
			a.secnam,
			a.grade,
			a.clacod,
			a.stuno,
			a.cname,
			a.deptno,
			a.seqno,
			a.attdepno,
			a.att_y,
			a.att_cls,
			a.att_grou,
			a.seldomain,
			a.cono,
			a.credit,
			a.termnum,
			a.crs_credit,
			a.smn,
			x.clweek AS col,
			x.t_t AS value
	FROM crsopenf_cte a
			OUTER APPLY
			(
				SELECT b.clweek, --星期
					   (
							 SELECT DISTINCT c.bcl + '-' + c.ecl + ','
							 FROM crstime_cte c
							 WHERE b.syear = c.syear AND b.sem = c.sem AND b.deptno = c.deptno AND b.seqno = c.seqno AND b.clweek = c.clweek
							 FOR XML PATH('')
					   ) t_t --上課時間
				FROM crstime_cte b
				WHERE a.syear = b.syear
				  AND a.sem = b.sem
				  --AND a.stuno = b.stuno
				  AND a.deptno = b.deptno
				  AND a.seqno = b.seqno
			) x
) t PIVOT (
     MAX([value]) 
	 FOR [col] IN ("1", "2", "3", "4", "5", "6", "7")
) p
--ORDER BY p.stuno,
--		 p.deptno,
--         p.seqno,
--		 p.cono
 
```
:::

---

:::spoiler REPLICATE 
    SELECT *,
           REPLICATE('1', h.level) 
    FROM questionnaires_cte h
:::

---

:::spoiler 判斷table或暫存表是否存在
```
　　IF EXISTS( SELECT * FROM sys.tables WHERE name = 'Ins_opd_check' )
	BEGIN  
		DROP TABLE Ins_opd_check		
	END

	IF object_id('tempdb..#chek_die') IS NOT NULL
	BEGIN  
		DROP TABLE #chek_die	
	END
```
:::

---

:::spoiler 日期轉換
```
 CAST(STR('1050101' + 19110000) AS DATETIME)
 
 RIGHT('00000000' + CAST(t.pat_no AS varchar), 8)	
 (CAST(FORMAT(DATEADD(YEAR,-1911,  CAST(a.enc_time AS date)), N'yyyMM') AS int))　
 CAST(STR(SUBSTRING(a.his_opd_no, 1, 7) + 19110000) AS date)  AS ODR_RO_DATE
```
:::

---

:::spoiler 欄位描述

```
SELECT *
FROM (
	  SELECT a.TABLE_NAME,
			a.COLUMN_NAME,
			 (
			   SELECT tc.CONSTRAINT_TYPE 
			   FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS tc
					 JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS kcu
					  ON tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME　AND tc.TABLE_SCHEMA = kcu.TABLE_SCHEMA　AND tc.TABLE_NAME = kcu.TABLE_NAME
			   WHERE tc.TABLE_NAME = a.TABLE_NAME
				 AND kcu.COLUMN_NAME = a.COLUMN_NAME  
			) AS CONSTRAINT_TYPE,
			( 
				 SELECT value   
				 FROM fn_listextendedproperty (NULL, 'schema', a.TABLE_SCHEMA, 'table', a.TABLE_NAME, 'column', default)   
				 WHERE name='MS_Description' and objtype='COLUMN' 
				   AND objname Collate Chinese_Taiwan_Stroke_CI_AS = a.COLUMN_NAME   
			) AS 欄位描述,
		  a.DATA_TYPE,		 
		  a.IS_NULLABLE
	 FROM (
		  SELECT a.TABLE_NAME,
			  b.COLUMN_NAME,
			  a.TABLE_SCHEMA,
			  b.DATA_TYPE,
			  b.IS_NULLABLE,
			  b.CHARACTER_SET_SCHEMA
		  FROM INFORMATION_SCHEMA.TABLES a
			LEFT JOIN INFORMATION_SCHEMA.COLUMNS b
			 ON a.TABLE_NAME = b.TABLE_NAME    
		  --WHERE a.TABLE_NAME LIKE '%opd_enc%'   
		  --　AND b.COLUMN_NAME = 'enc_json'
　	 ) a
) t
WHERE 
　　　　--t.TABLE_NAME LIKE '%D%'   
	  　--AND
	   t.COLUMN_NAME LIKE '%aplx_nor_a_no%'　
	　--AND
	　--CAST(t.欄位描述 AS nvarchar(100)) LIKE '%序號%'
　
--SELECT *
--FROM ho_micd



```

:::

---

:::spoiler split

```

WITH split AS (　

	SELECT *
	FROM (
		SELECT Split.a.value('.', 'NVARCHAR(MAX)') AS Value 
		FROM (	 
				SELECT CAST ('<M>' + REPLACE(CAST (nid_rec AS nvarchar(MAX)) , ',', '</M><M>') + '</M>' AS XML) AS Data
				FROM hg_mnid
				WHERE nid_id = '9301'
				  AND nid_code IN ('0')
　			       
		) AS A 
				CROSS APPLY Data.nodes ('/M') AS Split(a)
	) T
	WHERE T.Value LIKE '%糖尿病已進入第二階段管理照護不得再申報第一階段管理照護費%'  

)

SELECT *
FROM (
	SELECT Split.a.value('.', 'NVARCHAR(MAX)') AS Value 
	FROM (	 
			SELECT CAST ('<M>' + REPLACE(CAST (Value AS nvarchar(MAX)) , ':', '</M><M>') + '</M>' AS XML) AS Data
			FROM split			　
　			       
	) AS A 
			CROSS APPLY Data.nodes ('/M') AS Split(a)
) T
```
:::

---

:::spoiler SQL TO JSON
```
SELECT '' AS Id,
	　--　A.No AS No, 
		JSON_QUERY(
			'[' + 
					STUFF((
							SELECT ',' + '"' + a.hwchd_cid + '"' 
							FROM hw_mchd b 
							WHERE a.hwchd_oid = b.hwchd_oid
							FOR XML PATH ('')
						), 1, 1, '') 
			　+ ']'
		) AS json
FROM hw_mchd a
FOR JSON AUTO
 
```
:::

---