2016-06-08 54 views
1

任何人都可以幫助我解決一個常見問題,我偶爾會遇到一些常見問題,但往往會在很長的路上工作嗎?我試圖找到一個優雅的方式來確定表中不存在什麼Id給定一個大的值列表。查找id的記錄不存在IN表達式

我已經提供了一個包含4000多個字符串ID列表的Excel工作表,我需要確定哪些不存在於SQL Server表中。

我的第一個操作是使用Notepad ++並將列表轉換爲與'XX1','XX2','XX3'等類似的CSV列表,並運行SELECT * FROM [TABLE] WHERE [ID] IN(' XX1' , 'XX2', 'XX3',...)。這比Excel中顯示的記錄少2條記錄,所以現在我需要篩選它們以確定哪兩個不在數據庫中。

感謝您的任何幫助。

Paul。

+2

中查看此頁面通常情況下,您需要在一張表中檢查ID。然後,你可以左加入與記錄的實際表,看看有什麼缺失 –

+0

謝謝@juergend - thi是一種情況下,我沒有在桌子上的身份證 - 你這次在Excel中呈現給我(有時通過電子郵件或其他方式,但基本上在數據庫結構之外,否則它會更簡單) – Paul

+0

感謝@LukStorms獲取數據簡單地進入臨時表的任何提示,而無需過多編寫腳本?一旦它在那裏,我很滿意TSQL來做我需要的東西,但是我想知道是否有一種簡單的方法可以輕鬆地將列表放入db中,然後使用。 – Paul

回答

1

您可以針對使用表值構造函數生成的內聯表進行連接,前提是它不會溢出多個標識,在這種情況下需要將它們轉儲到表中。

在一個VALUES表達爲行的數量限制爲1000,根據the documentation

,可以通過在VALUES列表直接插入行來構造的最大行數是1000

要加入與內嵌表,使用語法:

INNER JOIN (VALUES (1), (2), ...) AS inline (id) 

下面是一個例子,W第i此表(實際表):

CREATE TABLE databasetable (ID INT NOT NULL) 
INSERT INTO databasetable VALUES (1), (2), (3), (5), (6), (8), (9), (10) 

您可以查詢這樣的遺漏值:

SELECT 
    excel.id 
FROM 
    databasetable AS A 
    RIGHT JOIN (VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10)) AS excel (id) 
     ON A.id = excel.id 
WHERE 
    A.id IS NULL 

你會因此有機會從你的Excel電子表格的VALUES (1), (2), (3), ...)

要使用臨時表,如果有超過1000行:

DECLARE @EXCEL TABLE (ID INT) 
INSERT INTO @EXCEL VALUES (1), (2), (3), ..... -- first 1000 
INSERT INTO @EXCEL VALUES (1), (2), (3), ..... -- next 1000 
INSERT INTO ...        -- and so on 

SELECT 
    @excel.id 
FROM 
    databasetable AS A 
    RIGHT JOIN @excel 
     ON A.id = @excel.id 
WHERE 
    A.id IS NULL 
+0

完美的謝謝!我之前使用過表值構造函數,但在這種情況下並沒有處理輸入列表格式,這對於超過4000個值來說是完美的,現在我發現了我的缺失ID!非常感謝! – Paul

+0

請注意我對可能的限制的評論。這可能是因爲你不能創建一個有4000行的內聯表,你將不得不看看有什麼作用。 –

+0

您可能想要在我的編輯後取消接受我的回答,請稍等片刻。 –

1

就在幾個演示的添加到possibilies

通過表格變量。
這一次與NOT IN子句:

DECLARE @varTbl TABLE(ID varchar(8)); 

insert into @varTbl values ('XX1'),('XX2'); 

select id from @varTbl 
where id not in (select distinct id from [SomeTable]); 

通過,只有在會話期間存在的臨時表。
這次用LEFT JOIN。

CREATE TABLE #tempTbl (ID varchar(8)); 

insert into #tempTbl values ('XX1'),('XX2'); 

select tmp.id 
from #tempTbl tmp 
left join [SomeTable] t on (tmp.id = t.id) 
where t.id is null 
group by tmp.id 
order by tmp.id; 

另一種完全不同的方法是通過文件進行比較。 您首先將參考數據的ID和目標表中的ID導出到已排序的文本文件。然後過濾掉參考數據中但不在目標表中的行的差異。
在Windows上,您可以通過PowerShell進行操作。

$ref = Get-Content WhatShouldBe.txt 
$dest = Get-Content WhatIsNow.txt 

Compare-Object $ref $dest |Where-Object {$_.SideIndicator -eq "<="} |Select -ExpandProperty InputObject > WhatCanBeAdded.txt 
+0

嗨Luk,這些例子將顯示數據庫中存在的記錄,但不存在於IN表達式中,這與我所尋找的相反,但是謝謝你的嘗試。 – Paul

+0

呵呵,我的確誤解了。修正了這些陳述。無論如何,原則是一樣的。 – LukStorms

+1

@Paul我想知道如何通過比較簡單的文本文件與ID的排序來在Windows上做到這一點。所以我添加了一個使用PowerShell的解決方案。 – LukStorms

1

相信你可以在數據庫中創建表

如果您在Excel工作表或電子郵件中的內容移動到一個Excel工作表,如果它的電子郵件或直接使用導入數據導入Excel工作表中獲取文件嚮導複製到登臺表 之後,您可以輕鬆比較登臺表和原始表中的數據,這比在表變量或#temp表中加載該標記更容易。 該視頻演示瞭如何導入Excel數據到SQL Server https://www.youtube.com/watch?v=Z1vqhYlwcyA

也做了隨機檢查,所有的值填充或者是任何NULL值插入也。

還有一件事要用IN子句添加,其中有成千上萬的值 會引發錯誤。請在SO "IN" clause limitation in Sql Server

+0

好處,特別是「IN」條款限制鏈接。謝謝! – Paul