带有复杂子查询的 SQL 查询

发布于 2024-09-13 13:22:37 字数 670 浏览 6 评论 0原文

我有两张桌子,Foo 和 Bar。 Foo 包含 Bar 的主键 (bar_id) 的外键。 Bar 的结构允许通过 Bar 中另一条记录的外键 (bar_parent_id) 与其自身建立父/子关系。这种关系是有限的,因此任何具有父级的 Bar 记录本身都不能是父级。然而,任何一个父母都可以有多个孩子。

我的查询需要选择 Foo 中与 Bar 中给定记录匹配的所有记录以及 Bar 的父母、孩子或兄弟姐妹。下面的查询可以工作,但速度有点慢。有什么方法可以使其运行得更快吗?

SELECT f.field1, f.field2
FROM Foo f
WHERE f.bar_id IN (
    SELECT bar_id 
    FROM Bar
    WHERE bar_id = @bar_id OR
    bar_parent_id = @bar_id OR 
    bar_id = (SELECT bar_parent_id FROM Bar WHERE bar_id = @bar_id) OR
    bar_parent_id = (SELECT bar_parent_id FROM Bar WHERE bar_id = @bar_id AND bar_parent_id > 0)
) 

PS 这是真实查询的简化版本。它实际上有第二个相同的子查询到另一个表,该表与 Bar 具有相同的自/父/子关系。

I have two tables, Foo and Bar. Foo contains a foreign key to Bar's primary key (bar_id). Bar is structured to allow a parent/child relationship to itself through a foreign key (bar_parent_id) to another record in Bar. This relationship is limited such that any Bar record that has a parent cannot itself be a parent. However, any given parent can have multiple children.

My query needs to select all of the records in Foo that match a given record in Bar as well any of the Bar's parents, children or siblings. The query below works, but is somewhat slow. Is there any way to structure it so that it will run faster?

SELECT f.field1, f.field2
FROM Foo f
WHERE f.bar_id IN (
    SELECT bar_id 
    FROM Bar
    WHERE bar_id = @bar_id OR
    bar_parent_id = @bar_id OR 
    bar_id = (SELECT bar_parent_id FROM Bar WHERE bar_id = @bar_id) OR
    bar_parent_id = (SELECT bar_parent_id FROM Bar WHERE bar_id = @bar_id AND bar_parent_id > 0)
) 

P.S. This is a simplified version of the real query. It actually has a second, identical subquery to another table that has the same self/parent/child relationship as Bar.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

审判长 2024-09-20 13:22:37

你可以尝试一下,但我不确定正确性

SELECT
    f.field1, f.field2 
FROM
    foo f 
    LEFT JOIN bar b
    LEFT JOIN bar bParent 
    ON b.parent_id = bParent.bar_id
    LEFT JOIN bar bChildren 
    ON b.bar_id = bChildren.Parent_id
WHERE
    b.bar_id = @bar_id
    or 
    bParent.bar_id = @bar_id
    or 
    bChildren.bar_id = @bar_id  

You can try but I'm not sure of the correctness

SELECT
    f.field1, f.field2 
FROM
    foo f 
    LEFT JOIN bar b
    LEFT JOIN bar bParent 
    ON b.parent_id = bParent.bar_id
    LEFT JOIN bar bChildren 
    ON b.bar_id = bChildren.Parent_id
WHERE
    b.bar_id = @bar_id
    or 
    bParent.bar_id = @bar_id
    or 
    bChildren.bar_id = @bar_id  
久光 2024-09-20 13:22:37

试试这个:

SELECT f.field1, f.field2
  FROM Foo f
 WHERE EXISTS(SELECT NULL
                FROM BAR b
               WHERE b.bar_id = f.bar_id
                 AND (    @bar_id IN (b.bar_id, b.bar_parent_id)
                       OR EXISTS(SELECT NULL
                                   FROM BAR x
                                  WHERE x.bar_parent_id = b.bar_id
                                    AND x.bar_id = @bar_id)
                       OR EXISTS(SELECT NULL
                                   FROM BAR y
                                  WHERE y.bar_parent_id = b.bar_parent_id
                                    AND y.bar_id = @bar_id
                                    AND y.bar_parent_id > 0))

Try this:

SELECT f.field1, f.field2
  FROM Foo f
 WHERE EXISTS(SELECT NULL
                FROM BAR b
               WHERE b.bar_id = f.bar_id
                 AND (    @bar_id IN (b.bar_id, b.bar_parent_id)
                       OR EXISTS(SELECT NULL
                                   FROM BAR x
                                  WHERE x.bar_parent_id = b.bar_id
                                    AND x.bar_id = @bar_id)
                       OR EXISTS(SELECT NULL
                                   FROM BAR y
                                  WHERE y.bar_parent_id = b.bar_parent_id
                                    AND y.bar_id = @bar_id
                                    AND y.bar_parent_id > 0))
甜心小果奶 2024-09-20 13:22:37

OR 通常会减慢 SQL 查询的速度。另一种可能性能更好的替代方案是合并单独查询的结果,如下所示:

SELECT f.field1, f.field2 FROM Foo f where f.bar_id = @bar_id
UNION
SELECT f.field1, f.field2 FROM Foo f 
JOIN Bar b on f.bar_id = b.bar_id and @bar_id = b.bar_parent_id
UNION
SELECT f.field1, f.field2 FROM Foo f 
JOIN Bar bsib on f.bar_id = bsib.bar_id 
JOIN Bar b on bsib.bar_parent_id = b.bar_parent_id and @bar_id = b.bar_id
UNION
SELECT f.field1, f.field2 FROM Foo f 
JOIN Bar bpar on bpar.bar_id = f.bar_id 
JOIN Bar b on bpar.bar_id = b.bar_parent_id and @bar_id = b.bar_id

ORs often slow down SQL queries. An alternative that may perform better is to union the result of separate queries, like so:

SELECT f.field1, f.field2 FROM Foo f where f.bar_id = @bar_id
UNION
SELECT f.field1, f.field2 FROM Foo f 
JOIN Bar b on f.bar_id = b.bar_id and @bar_id = b.bar_parent_id
UNION
SELECT f.field1, f.field2 FROM Foo f 
JOIN Bar bsib on f.bar_id = bsib.bar_id 
JOIN Bar b on bsib.bar_parent_id = b.bar_parent_id and @bar_id = b.bar_id
UNION
SELECT f.field1, f.field2 FROM Foo f 
JOIN Bar bpar on bpar.bar_id = f.bar_id 
JOIN Bar b on bpar.bar_id = b.bar_parent_id and @bar_id = b.bar_id
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文