假設有A、B兩張表,其中B表有A表的外鍵。在SQL查詢中,咱們常常有這樣的需求,須要根據B表中的條件篩選去查詢A表中的內容,以工做流查詢用戶的已辦流程爲例來講明:sql
一、歷史流程實例表act_hi_procinst:下述用A表代替ide
CREATE TABLE `act_hi_procinst` ( `ID_` varchar(64) COLLATE utf8_bin NOT NULL, `PROC_INST_ID_` varchar(64) COLLATE utf8_bin NOT NULL, `BUSINESS_KEY_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin NOT NULL, `START_TIME_` datetime(3) NOT NULL, `END_TIME_` datetime(3) DEFAULT NULL, `DURATION_` bigint(20) DEFAULT NULL, `START_USER_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `START_ACT_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `END_ACT_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `SUPER_PROCESS_INSTANCE_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `DELETE_REASON_` varchar(4000) COLLATE utf8_bin DEFAULT NULL, `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '', `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL, PRIMARY KEY (`ID_`), UNIQUE KEY `PROC_INST_ID_` (`PROC_INST_ID_`), KEY `ACT_IDX_HI_PRO_INST_END` (`END_TIME_`), KEY `ACT_IDX_HI_PRO_I_BUSKEY` (`BUSINESS_KEY_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
二、歷史節點權限辦理表ACT_HI_IDENTITYLINK:如下用B表代替code
CREATE TABLE `act_hi_identitylink` ( `ID_` varchar(64) COLLATE utf8_bin NOT NULL DEFAULT '', `GROUP_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `USER_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, PRIMARY KEY (`ID_`), KEY `ACT_IDX_HI_IDENT_LNK_USER` (`USER_ID_`), KEY `ACT_IDX_HI_IDENT_LNK_TASK` (`TASK_ID_`), KEY `ACT_IDX_HI_IDENT_LNK_PROCINST` (`PROC_INST_ID_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
三、A、B表關係說明 A表的PROC_INST_ID_字段與主鍵ID_字段值徹底相同,B表的PROC_INST_ID_字段做爲A表的外鍵。 一個流程對應A表的一條數據,但會對應B表的多條數據(每一個流程節點在辦理時都會往B表插入數據),B表的USER_ID_字段會記錄辦理用戶的ID,查詢用戶已辦流程即根據此字段過濾便可,好了背景介紹完畢。blog
四、查詢用戶已辦流程SQL寫法 1)子查詢(in方法)ci
SELECT DISTINCT RES.* FROM ACT_HI_PROCINST RES WHERE RES.PROC_INST_ID_ IN ( SELECT LINK.PROC_INST_ID_ FROM ACT_HI_IDENTITYLINK LINK WHERE LINK.USER_ID_ = 6742 )
2)子查詢(exists方法)工作流
SELECT DISTINCT RES.* FROM ACT_HI_PROCINST RES WHERE ( EXISTS ( SELECT LINK.USER_ID_ FROM ACT_HI_IDENTITYLINK LINK WHERE USER_ID_ = 6742 AND LINK.PROC_INST_ID_ = RES.PROC_INST_ID_ ) )
3)鏈接查詢(join方法)it
SELECT DISTINCT RES.* FROM ACT_HI_PROCINST RES JOIN ACT_HI_IDENTITYLINK LINK ON LINK.PROC_INST_ID_ = RES.PROC_INST_ID_ WHERE LINK.USER_ID_ = 6742
以上3種方法查詢結果均一致: 效率
五、sql語句對比date
1)查詢速度sql語句
當外層查詢結果集的數據量N較小時,優先選用方法2——子查詢(exists方法); 反之,當外層查詢結果集的數據量N較大時,優先推薦方法3——鏈接查詢(join方法);
2)如何選擇
分狀況: 若是最後只要求查詢A表種的字段內容, 而且外層查詢結果集的數據量N較小時則優先推薦方法2——子查詢(exists方法);
若是要求查詢的內容包含A、B兩個表的字段,或者外層查詢結果集的數據量N較大時則優先推薦方法3——鏈接查詢(join方法);
至於方法一——子查詢(in方法)基本不太建議,可讀性和效率均不佳,除非in後面是肯定的範圍,如b.status in(1,2,3,4)這種;若是你用了方法一不妨看看可否用其餘兩種方法代替,以提高可讀性和效率。
本文就到這兒了,平時常常用的sql查詢,今天簡單總結了下,但願對讀者有幫助。