用SQL取差集--5月11日的一次任務

VAC用WINDOWS。 CR+LF


任務材料 :

數據1:20W的數據 all_num.txt

格式:13020451023,32523,9135044120,20111101133450,0,0,20120501010101

數據2:2W的數據 filter_num.txt

格式:13020451023

任務目標:

要將20W條數據中剔除掉2W個數據。

步驟1:建表(10‘)

A_TEMP_123 存20W, A存 2W

CREATE TABLE A_TEMP_123
(
A1 VARCHAR2(30),
A2 VARCHAR2(30),
A3 VARCHAR2(30),
A4 VARCHAR2(30),
A5 VARCHAR2(30),
A6 VARCHAR2(30),
A7 VARCHAR2(30)
) ;

CREATE TABLE A

(

i VARCHAR2(30)

);

步驟2:建索引 (5’)

(A_TEMP_123.A1 與A.I存號碼)

CREATE INDEX IDX_A1 ON A_TEMP_123 (A1);

CREATE INDEX IDX_A2 ON A (I);

步驟3:文本格式整理(5‘)

dos2unix *.txt

步驟3:sqlldr 導入(10‘)

sqlldr 賬號/密碼 control=s1.ctl data=all_num.txt log=s1.log errors=10000

s1 內容:

load data
replace into table A_TEMP_123
fields terminated by ','(a1,a2,a3,a4,a5,a6,a7)

sqlldr 賬號/密碼 control=s2.ctl data=filter_num.txt log=s2.log errors=10000

s2 內容:

load data
replace into table A
fields terminated by ','(i)

步驟4:SQL查詢(10’)

2B方法:(半天出不了結果)

select count(1) from A_TEMP_123 t1 where t1.a1 not in (select t2.i from a t2 );

有四種:

1.用 in 關聯子查詢方法 :(比較慢)

SQL> select count(1) from A_TEMP_123 t1 where t1.a1 not in (select t2.i from a t2 where t2.i=t1.a1);

COUNT(1)
----------
203192

如何計算此查詢:SQL Server 通過將每一行的值代入內部查詢,考慮 A_TEMP_123 T1 表中的每一行是否都包括在結果中。
例如,
1:如果 SQL Server 首先檢查 13020451023,32523,9135044120,20111101133450,0,0,20120501010101  行,那麼變量 T1.A1 將取值 13020451023,
2:SQL Server 將該值代入內部查詢。select t2.i from a t2 where t2.i=13020451023,結果爲13020451023,
3:因此外部查詢計算爲:select count(1) from A_TEMP_123 t1 where 13020451023 not in (13020451023),結果爲假,因此不列入生成的新表。

由此可見,加上與不加 where t2.i=t1.a1 的2B算法 ,差別就在於where 13020451023 not in (x1,x2,x3...........xn)的Xn的個數差別,加上條件(關聯查詢)只有一兩個,不加的話在in中有2W個,運算量差了4個數量級啊!

2.用 exists 關聯子查詢方法 :
SQL> select count(1) from A_TEMP_123 t1 where not exists (select 1 from a t2 where t2.i=t1.a1);

COUNT(1)
----------
203192

同理,用exists就更快一點,因爲在select 1 from a t2 where t2.i=13020451023時,返回1,在外部查詢時:select count(1) from A_TEMP_123 t1 where not exists (1),由於使用not exists ,所以存在1 就不被插入新表。

3.用 MINUS方法:

SQL> select count(1) from a_temp_123 t1 where t1.A1 in (select A1 from a_temp_123 minus select i from a);

COUNT(1)
----------
203192

4.用left join方法:

SQL> select count(1) from A_TEMP_123 t1 left join a t2 on t1.a1=t2.i where t2.i is null;

COUNT(1)
----------
203192

步驟5:腳本導出數據(5‘)

#!/bin/sh

sqlplus-s xx/xx<<EOF >/dev/null

set trimspoolon headingoffnewpagenone feedofftermoff

spool after_filter.txt

select a1||','||a2||','||a3||','||a4||','||a5||','||a6||','||a7froma_temp_123 T1

where T1.A1in(select A1froma_temp_123minusselect ifroma);

spooloff

exit;

EOF

步驟6:壓縮

zip after_filter.zipafter_filter.txt

步驟7:下載到本機

解壓,轉換成windows格式!

這次數據提取,讓我懂得2B的SQL語句的執行效率差別有多大,愣是執行了1小時沒出數據,今後要多加強SQL的學習啊。

 

相關子查詢

許多查詢都可以通過執行一次子查詢並將得到的值代入外部查詢的 WHERE 子句中進行計算。在包括相關子查詢(也稱爲重複子查詢)的查詢中,子查詢依靠外部查詢獲得值。這意味着子查詢是重複執行的,爲外部查詢可能選擇的每一行均執行一次。

此查詢在 SalesPerson 表中檢索獎金爲 5000 且僱員標識號與 EmployeeSalesPerson 表中的標識號相匹配的僱員的名和姓的一個實例。

USE AdventureWorks2008R2;
GO
SELECT DISTINCT c.LastName, c.FirstName, e.BusinessEntityID 
FROM Person.Person AS c JOIN HumanResources.Employee AS e
ON e.BusinessEntityID = c.BusinessEntityID 
WHERE 5000.00 IN
    (SELECT Bonus
    FROM Sales.SalesPerson sp
    WHERE e.BusinessEntityID = sp.BusinessEntityID) ;
GO

下面是結果集:

LastName FirstName BusinessEntityID

-------------------------- ---------- ------------

Ansman-Wolfe Pamela 280

Saraiva José 282

(2 row(s) affected)

該語句中前面的子查詢無法獨立於外部查詢進行計算。它需要 Employee.BusinessEntityID 值,但是此值隨 SQL Server 檢查Employee 中的不同行而改變。

下面準確說明了如何計算此查詢:SQL Server 通過將每一行的值代入內部查詢,考慮Employee 表中的每一行是否都包括在結果中。例如,如果 SQL Server 首先檢查 Syed Abbas 行,那麼變量Employee.BusinessEntityID 將取值 285,SQL Server 將該值代入內部查詢。

USE AdventureWorks2008R2;
GO
SELECT Bonus
FROM Sales.SalesPerson
WHERE BusinessEntityID = 285;

結果爲 0(Syed Abbas 沒有收到獎金,因爲他不是銷售人員),因此外部查詢計算爲:

USE AdventureWorks2008R2;
GO
SELECT LastName, FirstName
FROM Person.Person AS c JOIN HumanResources.Employee AS e
ON e.BusinessEntityID = c.BusinessEntityID 
WHERE 5000 IN (0.00)

由於這是假的,因此 Syed Abbas 行不包括在結果中。對 Pamela Ansman-Wolfe 行運行相同的過程,您會發現此行沒有包括在結果中。

通過在外部查詢中引用表中的列作爲表值函數的參數,相關子查詢也可以在 FROM 子句中包含表值函數。在這種情況下,對於外部查詢的每一行,將根據子查詢計算表值函數。

------------------------------------------------------------------------------------------------------------


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章