SQL子查詢與鏈接查詢研究

假設有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種方法查詢結果均一致: image.png效率

五、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查詢,今天簡單總結了下,但願對讀者有幫助。

相關文章
相關標籤/搜索