Sql Server中Cross Apply關鍵字的使用 前言 在寫一個業務的時候,有1列數據如下: 車牌號 湘A00001/湘G00001 湘A00002/湘G00002 湘A00003/湘G00003/湘A8888888 湘A00004/湘G00004/湘A00001 我的查詢條件也是車牌號,我 ...
Sql Server中Cross Apply關鍵字的使用
前言
在寫一個業務的時候,有1列數據如下:
車牌號 |
---|
湘A00001/湘G00001 |
湘A00002/湘G00002 |
湘A00003/湘G00003/湘A8888888 |
湘A00004/湘G00004/湘A00001 |
我的查詢條件也是車牌號,我會傳入如下參數:
@PLATE_NO '湘A00003/湘G00003/湘A8888888'
我需要判斷我傳入的車牌號是否包含上面的列數據,舉例上面的表為B表,那麼B表列中的車牌號,我的PLATE_NO參數需要包含裡面所有的車牌號。
一個簡單的包含關係,我會用拆分函數去拆分我傳入的參數,然後去比對參數是否包含B表的車牌號。對於參數處理很簡單,但是B表的多行,那麼該如何去處理B表的列呢?
Cross Apply介紹
在 SQL Server 中,Cross Apply 關鍵字主要用於從一個表中獲取數據,並對每一行數據應用一個表值函數,然後返回函數的結果。這個關鍵字允許你在右側的表達式中引用左側表的列。
Cross Apply 和 Inner Join 類似,只返回匹配的記錄。如果沒有匹配的記錄,那麼就不會返回任何結果。
思路
首先肯定需要通過‘/’拆分獲得車牌號數據,將湘A00003/湘G00003/湘A8888888變成如下格式
col |
---|
湘A00003 |
湘G00003 |
湘A8888888 |
那麼B表該如何去實現,它有多行數據,多行數據如何拆分成一列。
代碼實現
首先我們需要有一個表值函數來拆分字元串:
CREATE FUNCTION dbo.SplitString
(
@List NVARCHAR(MAX),
@Delim NVARCHAR(255)
)
RETURNS TABLE
AS
RETURN
(
SELECT Item = y.i.value('(./text())[1]', 'nvarchar(4000)')
FROM
(
SELECT x = CONVERT(XML, '<i>'
+ REPLACE(@List, @Delim, '</i><i>')
+ '</i>').query('.')
) AS a CROSS APPLY x.nodes('i') AS y(i)
);
實現方式很多,我這裡直接讓GPT生成了一個,執行上述代碼即可完成拆分函數創建,調用如下:
SELECT Item FROM dbo.SplitString('湘A00003/湘G00003/湘A8888888', '/');
對於B表的操作,就需要使用到Cross Apply
關鍵字了,我對每一行數據車票號進行拆分操作,然後將數據存於臨時表,並去重處理。
SELECT DISTINCT
split.col
INTO #TEMP
FROM B
CROSS APPLY dbo.SplitString(車牌號, '/') AS split;
拆分結果如下
col |
---|
湘A00001 |
湘G00001 |
湘A00002 |
... |
然後在進行比對查詢
將參數存放在TEMP01
臨時表,將B表拆分的數據存於TEMP02
臨時表,然後使用CASE WHEN
以TEMP02
為主表判斷TEMP01
列是否存在與02中,不能存在則新建一列賦值為0
SELECT
P.Item,
CASE
WHEN EXISTS
(
SELECT 1 FROM TEMP01 WHERE Item = P.Item
) THEN
1
ELSE
0
END AS ISBOOL
FROM TEMP02 P
結果如下,這裡只是舉例子,主要是體現Cross Apply的作用。
總結
簡單來說 Cross Apply 看作是 SQL Server 中的一個"迴圈"操作。對於你在左邊的表中的每一行數據,Cross Apply 都會執行一次右邊的查詢。我上述的操作就是多列數據使用實現Cross Apply迴圈拆分每行數據的車牌號列。