获得 mysql 结果的最佳方式
Best way to get results for mysql
我的暑期实习项目确实需要一些帮助。我需要知道是否有 better/easier 方法。我有 9 table 的信息需要合并到 1 table。该项目旨在帮助限制基于 cl_no 和 c_no 的特定用户的访问权限。我们只想要基于 table 的不同 c_no cl_no。我首先编写以下脚本作为视图,以查看我将使用的所有相关记录。
SELECT DISTINCT
`contacts_callmeet`.`c_no` AS `c_no`,
`contacts_callmeet`.`ccm_cl_no` AS `ccm_cl_no`,
1 AS `ti_no`,
1 AS `ctc_status`,
`contacts_callmeet`.`a_no` AS `a_no`
FROM
`contacts_callmeet`
WHERE
((`contacts_callmeet`.`ccm_status` = 1)
AND (`contacts_callmeet`.`ccm_cl_no` IS NOT NULL)
AND (`contacts_callmeet`.`ccm_cl_no` <> 0))
UNION SELECT DISTINCT
`contacts_notes`.`c_no` AS `c_no`,
`contacts_notes`.`cl_no` AS `cl_no`,
2 AS `ti_no`,
1 AS `ctc_status`,
`contacts_notes`.`a_no` AS `a_no`
FROM
`contacts_notes`
WHERE
((`contacts_notes`.`cn_status` = 1)
AND (`contacts_notes`.`cl_no` IS NOT NULL)
AND (`contacts_notes`.`cl_no` <> 0)
AND (`contacts_notes`.`c_no` IS NOT NULL))
UNION SELECT DISTINCT
`d`.`c_no` AS `c_no`,
`d`.`cl_no` AS `cl_no`,
3 AS `ti_no`,
1 AS `ctc_status`,
`d`.`a_no` AS `a_no`
FROM
`disbursements` `d`
WHERE
((`d`.`disb_status` = 1)
AND (`d`.`cl_no` IS NOT NULL)
AND (`d`.`cl_no` <> 0)
AND (`d`.`c_no` IS NOT NULL))
UNION SELECT DISTINCT
`ea`.`c_no` AS `c_no`,
`e`.`cl_no` AS `cl_no`,
4 AS `ti_no`,
1 AS `ctc_status`,
`e`.`a_no` AS `a_no`
FROM
(`events_attendees` `ea`
JOIN `events` `e` ON ((`e`.`e_no` = `ea`.`e_no`)))
WHERE
((`ea`.`ea_status` = 1)
AND (`e`.`e_status` = 1)
AND (`e`.`cl_no` IS NOT NULL)
AND (`e`.`cl_no` <> 0)
AND (`ea`.`c_no` IS NOT NULL))
UNION SELECT DISTINCT
`gj`.`c_no` AS `c_no`,
`g`.`cl_no` AS `cl_no`,
5 AS `ti_no`,
1 AS `ctc_status`,
`g`.`a_no` AS `a_no`
FROM
(`groups` `g`
JOIN `groups_join` `gj` ON ((`g`.`g_no` = `gj`.`g_no`)))
WHERE
((`g`.`g_status` = 1)
AND (`g`.`cl_no` IS NOT NULL)
AND (`g`.`cl_no` <> 0)
AND (`gj`.`c_no` IS NOT NULL))
UNION SELECT DISTINCT
`pledges`.`c_no` AS `c_no`,
`pledges`.`cl_no` AS `cl_no`,
6 AS `ti_no`,
1 AS `ctc_status`,
`pledges`.`a_no` AS `a_no`
FROM
`pledges`
WHERE
((`pledges`.`pl_status` = 1)
AND (`pledges`.`cl_no` IS NOT NULL)
AND (`pledges`.`cl_no` <> 0)
AND (`pledges`.`c_no` IS NOT NULL))
UNION SELECT DISTINCT
`ec`.`c_no` AS `c_no`,
`e`.`cl_no` AS `cl_no`,
7 AS `ti_no`,
1 AS `ctc_status`,
`e`.`a_no` AS `a_no`
FROM
(`events_cohosts` `ec`
JOIN `events` `e` ON ((`e`.`e_no` = `ec`.`e_no`)))
WHERE
((`ec`.`ec_status` = 1)
AND (`e`.`e_status` = 1)
AND (`e`.`cl_no` IS NOT NULL)
AND (`e`.`cl_no` <> 0)
AND (`ec`.`c_no` IS NOT NULL))
UNION SELECT DISTINCT
`cl`.`c_no` AS `c_no`,
`clp`.`cl_no` AS `cl_no`,
8 AS `ti_no`,
1 AS `ctc_status`,
`cl`.`a_no` AS `a_no`
FROM
(`comm_list` `cl`
JOIN `comm_list_parent` `clp` ON ((`clp`.`clp_no` = `cl`.`clp_no`)))
WHERE
((`clp`.`clp_status` = 1)
AND (ISNULL(`cl`.`coml_status`)
OR (`cl`.`coml_status` = 1))
AND (`clp`.`cl_no` IS NOT NULL)
AND (`clp`.`cl_no` <> 0)
AND (`cl`.`c_no` IS NOT NULL))
UNION SELECT DISTINCT
`commitments`.`c_no` AS `c_no`,
`commitments`.`cl_no` AS `cl_no`,
9 AS `ti_no`,
1 AS `ctc_status`,
`commitments`.`a_no` AS `a_no`
FROM
`commitments`
WHERE
((`commitments`.`commit_status` = 1)
AND (`commitments`.`cl_no` IS NOT NULL)
AND (`commitments`.`cl_no` <> 0)
AND (`commitments`.`c_no` IS NOT NULL))
然后我意识到运行时间太长(50+ 秒)所以我开始为每个 table 编写触发器来填充一个名为 contacts_table_clients 的 table(见下文)。一个 table 的触发器如下所示。
ctc_no, c_no, cl_no, ti_no, ctc_status, a_no
88, 6972179, 2000, 2, 1, 151
CREATE DEFINER=`IDPAdmin`@`%` TRIGGER `IDP1`.`contacts_notes_AFTER_INSERT` AFTER INSERT ON `contacts_notes` FOR EACH ROW
BEGIN
DECLARE records int(10);
IF new.cl_no is not null
THEN
select count(c_no) into records from contacts_notes where cn_status = 1 and c_no = new.c_no and cl_no is not null and cl_no not in
(select cl_no from contacts_table_clients where ctc_status = 1 and c_no = new.c_no and ti_no = 2);
END IF;
IF records > 0
THEN
INSERT INTO `IDP1`.`contacts_table_clients`
(`c_no`,
`cl_no`,
`ti_no`,
`a_no`)
VALUES
(new.c_no,
new.cl_no,
2,
new.a_no);
END IF;
CREATE DEFINER=`IDPAdmin`@`%` TRIGGER `IDP1`.`contacts_notes_AFTER_UPDATE` AFTER UPDATE ON `contacts_notes` FOR EACH ROW
BEGIN
DECLARE old_cl_no int(10);
DECLARE new_cl_no int(10);
DECLARE delete_c_no int(10);
DECLARE delete_cl_no int(10);
DECLARE records int(10);
DECLARE records_2 int(10);
DECLARE old_cl_no_select int(10);
DECLARE new_cl_no_select int(10);
IF new.cl_no > 0 and old.cl_no is null
THEN
DROP TEMPORARY TABLE IF EXISTS tmp_contacts_notes_2;
create temporary table tmp_contacts_notes_2
select c_no, cl_no,a_no from contacts_notes where cn_status = 1 and c_no = new.c_no and cl_no is not null and cl_no not in
(select cl_no from contacts_table_clients where ctc_status = 1 and ti_no = 2 and c_no = new.c_no);
select count(*) into records_2 from tmp_contacts_notes_2;
END IF;
IF records_2 > 0
THEN
INSERT INTO `IDP1`.`contacts_table_clients`
(`c_no`,
`cl_no`,
`ti_no`,
`a_no`)
VALUES
(new.c_no,
new.cl_no,
2,
new.a_no);
END IF;
IF new.cn_status = 0 or new.cl_no is null
THEN
select distinct c_no into delete_c_no
from contacts_table_clients
where ctc_status = 1
and ti_no = 2
and c_no = new.c_no
and cl_no not in (select cl_no
from contacts_notes
where c_no = new.c_no
and cn_status = 1
and cl_no is not null);
select distinct cl_no into delete_cl_no
from contacts_table_clients
where ctc_status = 1
and ti_no = 2
and c_no = new.c_no
and cl_no not in (select cl_no
from contacts_notes
where c_no = new.c_no
and cn_status = 1
and cl_no is not null);
UPDATE contacts_table_clients
set ctc_status = 0
where ti_no = 2
and c_no = delete_c_no
and cl_no = delete_cl_no;
END IF;
IF new.cl_no <> old.cl_no and new.cl_no is not null and new.cl_no <> 0
THEN
select cl_no into old_cl_no
from contacts_table_clients
where ti_no = 2
and ctc_status = 1
and c_no = new.c_no
and cl_no not in (select cl_no
from contacts_notes
where c_no = new.c_no
and cn_status = 1
and cl_no is not null);
select cl_no into new_cl_no
from contacts_notes
where c_no = new.c_no
and cn_status = 1
and cl_no not in (select cl_no
from contacts_table_clients
where ti_no = 2
and c_no = new.c_no
and ctc_status = 1
and cl_no is not null);
END IF;
IF new_cl_no > 0 and old_cl_no > 0
THEN
UPDATE contacts_table_clients set cl_no = new_cl_no where ctc_status = 1 and ti_no = 1 and c_no = new.c_no and cl_no = old_cl_no;
END IF;
IF new.cl_no <> old.cl_no and new.cl_no is not null and new.cl_no <> 0
THEN
select distinct cl_no into delete_cl_no
from contacts_table_clients
where ctc_status = 1
and ti_no = 2
and c_no = new.c_no
and cl_no not in (select cl_no
from contacts_notes
where c_no = new.c_no
and cn_status = 1
and cl_no is not null);
UPDATE contacts_table_clients
set ctc_status = 0
where ti_no = 2
and c_no = new.c_no
and cl_no = delete_cl_no;
END IF;
IF delete_cl_no < 0 and (old_cl_no is null or new_cl_no is null or new_cl_no < 1 or old_cl_no < 1)
THEN
INSERT INTO `IDP1`.`contacts_table_clients`
(`c_no`,
`cl_no`,
`ti_no`,
`a_no`)
VALUES
(new.c_no,
new.cl_no,
2,
new.a_no);
END IF;
IF new.cl_no <> old.cl_no and old_cl_no > 0 and new.cl_no is not null
THEN
DROP TEMPORARY TABLE IF EXISTS tmp_contacts_notes;
create temporary table tmp_contacts_notes
select c_no, cl_no,a_no from contacts_notes where cn_status = 1 and c_no = new.c_no and cl_no is not null and cl_no not in
(select cl_no from contacts_table_clients where ctc_status = 1 and ti_no = 2 and c_no = new.c_no);
select count(*) into records from tmp_contacts_notes;
END IF;
IF records > 0
THEN
INSERT INTO `IDP1`.`contacts_table_clients`
(`c_no`,
`cl_no`,
`ti_no`,
`a_no`
)
VALUES
(new.c_no,
new.cl_no,
2,
new.a_no);
END IF;
IF new.cl_no <> old.cl_no and new.cl_no is not null and new.cl_no <> 0
THEN
select count(cl_no) into old_cl_no_select
from contacts_notes
where c_no = new.c_no
and cn_status = 1
and cl_no is not null
and cl_no not in (select cl_no
from contacts_table_clients
where ti_no = 2
and ctc_status = 1
and c_no = new.c_no);
END IF;
IF old_cl_no_select > 0
THEN
INSERT INTO `IDP1`.`contacts_table_clients`
(`c_no`,
`cl_no`,
`ti_no`,
`a_no`)
VALUES
(new.c_no,
new.cl_no,
2,
new.a_no);
END IF;
END
感谢您的帮助!
工会还行。
首先将 SQL 个语句分开,然后观察每个语句需要多长时间。
我猜其中一两个查询相当大 table。做一个 Explain
来找出什么需要这么长时间。可能缺少一些索引。
像这样添加它们:
ALTER TABLE `contacts_callmeet` ADD INDEX `ccm_status` (`ccm_status`)
我最近遇到了一个问题,并以类似的方式解决了它。似乎 MySQL 处理单独的 table 索引比使用连接 and/or 联合更好。
这种方法很好(我在第一个查询中获得了大约 1500 倍的性能提升),也正如 Thorsten 所说:考虑是否要在并集之前进行 distinct。也许你想要那个,我想当你最后做一个 distinct 时,结果会更快。
我的暑期实习项目确实需要一些帮助。我需要知道是否有 better/easier 方法。我有 9 table 的信息需要合并到 1 table。该项目旨在帮助限制基于 cl_no 和 c_no 的特定用户的访问权限。我们只想要基于 table 的不同 c_no cl_no。我首先编写以下脚本作为视图,以查看我将使用的所有相关记录。
SELECT DISTINCT
`contacts_callmeet`.`c_no` AS `c_no`,
`contacts_callmeet`.`ccm_cl_no` AS `ccm_cl_no`,
1 AS `ti_no`,
1 AS `ctc_status`,
`contacts_callmeet`.`a_no` AS `a_no`
FROM
`contacts_callmeet`
WHERE
((`contacts_callmeet`.`ccm_status` = 1)
AND (`contacts_callmeet`.`ccm_cl_no` IS NOT NULL)
AND (`contacts_callmeet`.`ccm_cl_no` <> 0))
UNION SELECT DISTINCT
`contacts_notes`.`c_no` AS `c_no`,
`contacts_notes`.`cl_no` AS `cl_no`,
2 AS `ti_no`,
1 AS `ctc_status`,
`contacts_notes`.`a_no` AS `a_no`
FROM
`contacts_notes`
WHERE
((`contacts_notes`.`cn_status` = 1)
AND (`contacts_notes`.`cl_no` IS NOT NULL)
AND (`contacts_notes`.`cl_no` <> 0)
AND (`contacts_notes`.`c_no` IS NOT NULL))
UNION SELECT DISTINCT
`d`.`c_no` AS `c_no`,
`d`.`cl_no` AS `cl_no`,
3 AS `ti_no`,
1 AS `ctc_status`,
`d`.`a_no` AS `a_no`
FROM
`disbursements` `d`
WHERE
((`d`.`disb_status` = 1)
AND (`d`.`cl_no` IS NOT NULL)
AND (`d`.`cl_no` <> 0)
AND (`d`.`c_no` IS NOT NULL))
UNION SELECT DISTINCT
`ea`.`c_no` AS `c_no`,
`e`.`cl_no` AS `cl_no`,
4 AS `ti_no`,
1 AS `ctc_status`,
`e`.`a_no` AS `a_no`
FROM
(`events_attendees` `ea`
JOIN `events` `e` ON ((`e`.`e_no` = `ea`.`e_no`)))
WHERE
((`ea`.`ea_status` = 1)
AND (`e`.`e_status` = 1)
AND (`e`.`cl_no` IS NOT NULL)
AND (`e`.`cl_no` <> 0)
AND (`ea`.`c_no` IS NOT NULL))
UNION SELECT DISTINCT
`gj`.`c_no` AS `c_no`,
`g`.`cl_no` AS `cl_no`,
5 AS `ti_no`,
1 AS `ctc_status`,
`g`.`a_no` AS `a_no`
FROM
(`groups` `g`
JOIN `groups_join` `gj` ON ((`g`.`g_no` = `gj`.`g_no`)))
WHERE
((`g`.`g_status` = 1)
AND (`g`.`cl_no` IS NOT NULL)
AND (`g`.`cl_no` <> 0)
AND (`gj`.`c_no` IS NOT NULL))
UNION SELECT DISTINCT
`pledges`.`c_no` AS `c_no`,
`pledges`.`cl_no` AS `cl_no`,
6 AS `ti_no`,
1 AS `ctc_status`,
`pledges`.`a_no` AS `a_no`
FROM
`pledges`
WHERE
((`pledges`.`pl_status` = 1)
AND (`pledges`.`cl_no` IS NOT NULL)
AND (`pledges`.`cl_no` <> 0)
AND (`pledges`.`c_no` IS NOT NULL))
UNION SELECT DISTINCT
`ec`.`c_no` AS `c_no`,
`e`.`cl_no` AS `cl_no`,
7 AS `ti_no`,
1 AS `ctc_status`,
`e`.`a_no` AS `a_no`
FROM
(`events_cohosts` `ec`
JOIN `events` `e` ON ((`e`.`e_no` = `ec`.`e_no`)))
WHERE
((`ec`.`ec_status` = 1)
AND (`e`.`e_status` = 1)
AND (`e`.`cl_no` IS NOT NULL)
AND (`e`.`cl_no` <> 0)
AND (`ec`.`c_no` IS NOT NULL))
UNION SELECT DISTINCT
`cl`.`c_no` AS `c_no`,
`clp`.`cl_no` AS `cl_no`,
8 AS `ti_no`,
1 AS `ctc_status`,
`cl`.`a_no` AS `a_no`
FROM
(`comm_list` `cl`
JOIN `comm_list_parent` `clp` ON ((`clp`.`clp_no` = `cl`.`clp_no`)))
WHERE
((`clp`.`clp_status` = 1)
AND (ISNULL(`cl`.`coml_status`)
OR (`cl`.`coml_status` = 1))
AND (`clp`.`cl_no` IS NOT NULL)
AND (`clp`.`cl_no` <> 0)
AND (`cl`.`c_no` IS NOT NULL))
UNION SELECT DISTINCT
`commitments`.`c_no` AS `c_no`,
`commitments`.`cl_no` AS `cl_no`,
9 AS `ti_no`,
1 AS `ctc_status`,
`commitments`.`a_no` AS `a_no`
FROM
`commitments`
WHERE
((`commitments`.`commit_status` = 1)
AND (`commitments`.`cl_no` IS NOT NULL)
AND (`commitments`.`cl_no` <> 0)
AND (`commitments`.`c_no` IS NOT NULL))
然后我意识到运行时间太长(50+ 秒)所以我开始为每个 table 编写触发器来填充一个名为 contacts_table_clients 的 table(见下文)。一个 table 的触发器如下所示。
ctc_no, c_no, cl_no, ti_no, ctc_status, a_no
88, 6972179, 2000, 2, 1, 151
CREATE DEFINER=`IDPAdmin`@`%` TRIGGER `IDP1`.`contacts_notes_AFTER_INSERT` AFTER INSERT ON `contacts_notes` FOR EACH ROW
BEGIN
DECLARE records int(10);
IF new.cl_no is not null
THEN
select count(c_no) into records from contacts_notes where cn_status = 1 and c_no = new.c_no and cl_no is not null and cl_no not in
(select cl_no from contacts_table_clients where ctc_status = 1 and c_no = new.c_no and ti_no = 2);
END IF;
IF records > 0
THEN
INSERT INTO `IDP1`.`contacts_table_clients`
(`c_no`,
`cl_no`,
`ti_no`,
`a_no`)
VALUES
(new.c_no,
new.cl_no,
2,
new.a_no);
END IF;
CREATE DEFINER=`IDPAdmin`@`%` TRIGGER `IDP1`.`contacts_notes_AFTER_UPDATE` AFTER UPDATE ON `contacts_notes` FOR EACH ROW
BEGIN
DECLARE old_cl_no int(10);
DECLARE new_cl_no int(10);
DECLARE delete_c_no int(10);
DECLARE delete_cl_no int(10);
DECLARE records int(10);
DECLARE records_2 int(10);
DECLARE old_cl_no_select int(10);
DECLARE new_cl_no_select int(10);
IF new.cl_no > 0 and old.cl_no is null
THEN
DROP TEMPORARY TABLE IF EXISTS tmp_contacts_notes_2;
create temporary table tmp_contacts_notes_2
select c_no, cl_no,a_no from contacts_notes where cn_status = 1 and c_no = new.c_no and cl_no is not null and cl_no not in
(select cl_no from contacts_table_clients where ctc_status = 1 and ti_no = 2 and c_no = new.c_no);
select count(*) into records_2 from tmp_contacts_notes_2;
END IF;
IF records_2 > 0
THEN
INSERT INTO `IDP1`.`contacts_table_clients`
(`c_no`,
`cl_no`,
`ti_no`,
`a_no`)
VALUES
(new.c_no,
new.cl_no,
2,
new.a_no);
END IF;
IF new.cn_status = 0 or new.cl_no is null
THEN
select distinct c_no into delete_c_no
from contacts_table_clients
where ctc_status = 1
and ti_no = 2
and c_no = new.c_no
and cl_no not in (select cl_no
from contacts_notes
where c_no = new.c_no
and cn_status = 1
and cl_no is not null);
select distinct cl_no into delete_cl_no
from contacts_table_clients
where ctc_status = 1
and ti_no = 2
and c_no = new.c_no
and cl_no not in (select cl_no
from contacts_notes
where c_no = new.c_no
and cn_status = 1
and cl_no is not null);
UPDATE contacts_table_clients
set ctc_status = 0
where ti_no = 2
and c_no = delete_c_no
and cl_no = delete_cl_no;
END IF;
IF new.cl_no <> old.cl_no and new.cl_no is not null and new.cl_no <> 0
THEN
select cl_no into old_cl_no
from contacts_table_clients
where ti_no = 2
and ctc_status = 1
and c_no = new.c_no
and cl_no not in (select cl_no
from contacts_notes
where c_no = new.c_no
and cn_status = 1
and cl_no is not null);
select cl_no into new_cl_no
from contacts_notes
where c_no = new.c_no
and cn_status = 1
and cl_no not in (select cl_no
from contacts_table_clients
where ti_no = 2
and c_no = new.c_no
and ctc_status = 1
and cl_no is not null);
END IF;
IF new_cl_no > 0 and old_cl_no > 0
THEN
UPDATE contacts_table_clients set cl_no = new_cl_no where ctc_status = 1 and ti_no = 1 and c_no = new.c_no and cl_no = old_cl_no;
END IF;
IF new.cl_no <> old.cl_no and new.cl_no is not null and new.cl_no <> 0
THEN
select distinct cl_no into delete_cl_no
from contacts_table_clients
where ctc_status = 1
and ti_no = 2
and c_no = new.c_no
and cl_no not in (select cl_no
from contacts_notes
where c_no = new.c_no
and cn_status = 1
and cl_no is not null);
UPDATE contacts_table_clients
set ctc_status = 0
where ti_no = 2
and c_no = new.c_no
and cl_no = delete_cl_no;
END IF;
IF delete_cl_no < 0 and (old_cl_no is null or new_cl_no is null or new_cl_no < 1 or old_cl_no < 1)
THEN
INSERT INTO `IDP1`.`contacts_table_clients`
(`c_no`,
`cl_no`,
`ti_no`,
`a_no`)
VALUES
(new.c_no,
new.cl_no,
2,
new.a_no);
END IF;
IF new.cl_no <> old.cl_no and old_cl_no > 0 and new.cl_no is not null
THEN
DROP TEMPORARY TABLE IF EXISTS tmp_contacts_notes;
create temporary table tmp_contacts_notes
select c_no, cl_no,a_no from contacts_notes where cn_status = 1 and c_no = new.c_no and cl_no is not null and cl_no not in
(select cl_no from contacts_table_clients where ctc_status = 1 and ti_no = 2 and c_no = new.c_no);
select count(*) into records from tmp_contacts_notes;
END IF;
IF records > 0
THEN
INSERT INTO `IDP1`.`contacts_table_clients`
(`c_no`,
`cl_no`,
`ti_no`,
`a_no`
)
VALUES
(new.c_no,
new.cl_no,
2,
new.a_no);
END IF;
IF new.cl_no <> old.cl_no and new.cl_no is not null and new.cl_no <> 0
THEN
select count(cl_no) into old_cl_no_select
from contacts_notes
where c_no = new.c_no
and cn_status = 1
and cl_no is not null
and cl_no not in (select cl_no
from contacts_table_clients
where ti_no = 2
and ctc_status = 1
and c_no = new.c_no);
END IF;
IF old_cl_no_select > 0
THEN
INSERT INTO `IDP1`.`contacts_table_clients`
(`c_no`,
`cl_no`,
`ti_no`,
`a_no`)
VALUES
(new.c_no,
new.cl_no,
2,
new.a_no);
END IF;
END
感谢您的帮助!
工会还行。
首先将 SQL 个语句分开,然后观察每个语句需要多长时间。
我猜其中一两个查询相当大 table。做一个 Explain
来找出什么需要这么长时间。可能缺少一些索引。
像这样添加它们:
ALTER TABLE `contacts_callmeet` ADD INDEX `ccm_status` (`ccm_status`)
我最近遇到了一个问题,并以类似的方式解决了它。似乎 MySQL 处理单独的 table 索引比使用连接 and/or 联合更好。
这种方法很好(我在第一个查询中获得了大约 1500 倍的性能提升),也正如 Thorsten 所说:考虑是否要在并集之前进行 distinct。也许你想要那个,我想当你最后做一个 distinct 时,结果会更快。