【问题标题】:MySQL: filter child records, include all siblingsMySQL:过滤子记录,包括所有兄弟姐妹
【发布时间】:2021-05-29 00:13:52
【问题描述】:

有两个 MySQL 表:

tparent(id int, some data...)
tchild(id int, parent_id int, some data...)

我需要返回至少有一个子项符合某些条件的所有列(父项加上所有子项)。

我目前的解决方案:

-- prepare sample data
DROP TABLE IF EXISTS tparent;
DROP TABLE IF EXISTS tchild;

CREATE TABLE tparent (id int, c1 varchar(10), c2 date, c3 float);
CREATE TABLE tchild(id int, parent_id int, c4 float, c5 varchar(20), c6 date);
CREATE UNIQUE INDEX tparent_id_IDX USING BTREE ON tparent (id);
CREATE UNIQUE INDEX tchild_id_IDX USING BTREE ON tchild (id);

INSERT INTO tparent 
VALUES
  (1, 'a', '2021-01-01', 1.23)
, (2, 'b', '2021-02-01', 1.32)
, (3, 'c', '2021-01-03', 2.31);

INSERT INTO tchild
VALUES
  (10, 1, 22.333, 'argh1', '2000-01-01')
, (20, 1, 33.222, 'argh2', '2000-01-02')
, (30, 1, 44.555, 'argh3', '2000-02-02')
, (40, 2, 33.222, 'argh4', '2000-03-02')
, (50, 3, 33.222, 'argh5', '2000-04-02')
, (60, 3, 33.222, 'argh6', '2000-05-02');


-- the query
WITH parent_filter AS
(
SELECT
    parent_id
FROM
    tchild
WHERE
    c4>44
)
SELECT
    p.*,
    c.*
FROM
    tparent p
JOIN tchild c ON p.id = c.parent_id
JOIN parent_filter pf ON p.id = pf.parent_id;

它为父 id 1 和子 id 10、20、30 返回 3 行,因为子 id 30 具有匹配记录。它不会返回任何其他父 ID 的数据。

但是,我在这里查询了两次tchild(首先在 CTE 中,然后再次在主查询中)。由于两个表都比较大(10 到 1 亿行,每个父记录平均有 2-5 个子记录),我遇到了性能/时间问题。

有没有更好的方法来实现这种过滤? IE。无需多次查询tchild 表?

【问题讨论】:

标签: mysql sql filtering inner-join query-optimization


【解决方案1】:

你试过这个版本吗?

SELECT *
FROM tparent p
JOIN tchild c ON p.id = c.parent_id AND <criteria>

这样你在实际加入之前用 createria 限制 tchild 表

【讨论】:

  • 这将过滤掉父级的其他子记录。我需要包含父母的所有子记录,而不仅仅是匹配的记录。
【解决方案2】:

也许你可以改用这个:

select p.*, c.*
from tparent p
join tchild c 
on p.id = c.parent_id 
where exists (select 1 from tchild where <crtiteria>)

当子表中至少有一条记录满足条件时,这应该检索父子连接的所有行。

【讨论】:

    猜你喜欢
    • 2019-05-06
    • 1970-01-01
    • 2015-03-22
    • 1970-01-01
    • 2012-10-28
    • 1970-01-01
    • 1970-01-01
    • 2022-08-19
    • 1970-01-01
    相关资源
    最近更新 更多