假設(shè)有A、B兩張表焦除,其中B表有A表的外鍵。在SQL查詢中作彤,我們經(jīng)常有這樣的需求膘魄,需要根據(jù)B表中的條件篩選去查詢A表中的內(nèi)容,以工作流查詢用戶的已辦流程為例來(lái)說(shuō)明:
1竭讳、歷史流程實(shí)例表act_hi_procinst:下述用A表代替
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;
2创葡、歷史節(jié)點(diǎn)權(quán)限辦理表ACT_HI_IDENTITYLINK:以下用B表代替
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;
3、A绢慢、B表關(guān)系說(shuō)明
A表的PROC_INST_ID_字段與主鍵ID_字段值完全相同灿渴,B表的PROC_INST_ID_字段作為A表的外鍵。
一個(gè)流程對(duì)應(yīng)A表的一條數(shù)據(jù)胰舆,但會(huì)對(duì)應(yīng)B表的多條數(shù)據(jù)(每個(gè)流程節(jié)點(diǎn)在辦理時(shí)都會(huì)往B表插入數(shù)據(jù))逻杖,B表的USER_ID_字段會(huì)記錄辦理用戶的ID,查詢用戶已辦流程即根據(jù)此字段過(guò)濾即可思瘟,好了背景介紹完畢。
4闻伶、查詢用戶已辦流程SQL寫法
1)子查詢(in方法)
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方法)
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種方法查詢結(jié)果均一致:
5滨攻、sql語(yǔ)句對(duì)比
1)查詢速度
當(dāng)外層查詢結(jié)果集的數(shù)據(jù)量N較小時(shí),優(yōu)先選用方法2——子查詢(exists方法);
反之光绕,當(dāng)外層查詢結(jié)果集的數(shù)據(jù)量N較大時(shí)女嘲,優(yōu)先推薦方法3——連接查詢(join方法);
2)如何選擇
分情況:
如果最后只要求查詢A表種的字段內(nèi)容诞帐, 并且外層查詢結(jié)果集的數(shù)據(jù)量N較小時(shí)則優(yōu)先推薦方法2——子查詢(exists方法)欣尼;
如果要求查詢的內(nèi)容包含A、B兩個(gè)表的字段停蕉,或者外層查詢結(jié)果集的數(shù)據(jù)量N較大時(shí)則優(yōu)先推薦方法3——連接查詢(join方法)愕鼓;
至于方法一——子查詢(in方法)基本不太建議,可讀性和效率均不佳慧起,除非in后面是確定的范圍菇晃,如b.status in(1,2,3,4)這種;如果你用了方法一不妨看看能否用其他兩種方法代替蚓挤,以提升可讀性和效率磺送。
本文就到這兒了,平時(shí)經(jīng)常用的sql查詢灿意,今天簡(jiǎn)單總結(jié)了下估灿,希望對(duì)讀者有幫助。