在多个表上执行条件 mysql 连接的最有效方法? (Yii PHP框架)

发布于 2024-09-07 02:18:37 字数 1579 浏览 5 评论 0原文

我有五个表:

  1. tab_template
  2. template_group
  3. group
  4. user_group
  5. user

Tab_template 通过 template_group 关系表组织成组。 用户通过 user_group 关系表组织成组。 组可以是公共的或私有的(使用表中的tinyint 布尔列)。

我想查询以下所有 tab_templates:

  1. 与用户位于同一组中
  2. 或位于公共组中

这是我当前的查询:

SELECT * FROM tab_template t
左连接 template_group
ON template_group.tab_template_id=t.id
左连接
ON template_group.tab_template_id=group.id
左连接user_group
真实
哪里
群组私人=0

(template_group.group_id=user_group.group_id

user_group.user_id=2)
GROUP BY t.id;

它有效,而且本身并不是超级慢,但我加入 user_group 表的方式很糟糕。

问题是我需要加入 user_group 表进行条件检查,但我只需要在组不是私有的情况下进行条件检查。

我知道,而不是第三个 LEFT JOIN 与ON TRUE 条件下,我可以向 FROM 子句添加另一个表(FROM tab_template t, user_group ug)。但我不能这样做,因为 Yii 的 ActiveRecord 类与 DcCriteria 的工作方式我无法修改语句的这一部分。我可以编辑查询的任何其他部分,但不能编辑 FROM 子句。在此处查看 API:http://www.yiiframework.com/doc/api/CDbCriteria< /a> 这就是为什么我按照我的方式加入 user_group 表。一些 Yii 专家可能能够帮助我解决这个问题,但我不确定通过 FROMing 表而不是 JOINing 查询会更快。

任何帮助将不胜感激!谢谢

I have five tables:

  1. tab_template
  2. template_group
  3. group
  4. user_group
  5. user

Tab_template's are organized into groups with the template_group relational table.
Users's are organized into groups with the user_group relational table.
Group's can be public or private (using a tinyint boolean column in the table).

I want to query for all of the tab_templates that are either:

  1. In the same group as the user
  2. Or in a Public group

Here is my current query:

SELECT * FROM tab_template t
LEFT JOIN template_group
ON template_group.tab_template_id=t.id
LEFT JOIN group
ON template_group.tab_template_id=group.id
LEFT JOIN user_group
ON TRUE
WHERE
group.private=0
OR
(template_group.group_id=user_group.group_id
AND
user_group.user_id=2)
GROUP BY t.id;

It works, and it's not SUPER slow per se, but it's hacky the way I join in the user_group table.

The problem is that I need to JOIN the user_group table for a conditional check, but I only need to do that conditional check IF the group is not private.

I know that instead of the third LEFT JOIN with the ON TRUE condition I could add another table to the FROM clause (FROM tab_template t, user_group ug)... but I can't do that because the way Yii's ActiveRecord class works with the DcCriteria I can't modify that part of the statement. I can edit just about any other part of the query but not the FROM clause. Check out the API here: http://www.yiiframework.com/doc/api/CDbCriteria So that's why I am JOINing the user_group table the way I am. Some Yii experts might be able to help me solve that problem, but I'm not sure my query will be faster by FROMing the tables instead of the JOINing them anyway.

Any help would be greatly appreciated! Thanks

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

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

发布评论

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

评论(2

诗酒趁年少 2024-09-14 02:18:37

对于此类情况,我的建议是使用 UNION:

SELECT t.* 
  FROM TAB_TEMPLATE t
  JOIN TEMPLATE_GROUP tg ON tg.tab_template_id = t.id
  JOIN GROUP g ON g.id = tg.tab_template_id  
              AND g.private = 0
UNION 
SELECT t.* 
  FROM TAB_TEMPLATE t
  JOIN TEMPLATE_GROUP tg ON tg.tab_template_id = t.id
  JOIN GROUP g ON g.id = tg.tab_template_id  
              AND g.private != 0
  JOIN USER_GROUP ug ON ug.group_id = g.id

更容易阅读,这使得维护更容易。

My recommendation for situations like these is to use a UNION:

SELECT t.* 
  FROM TAB_TEMPLATE t
  JOIN TEMPLATE_GROUP tg ON tg.tab_template_id = t.id
  JOIN GROUP g ON g.id = tg.tab_template_id  
              AND g.private = 0
UNION 
SELECT t.* 
  FROM TAB_TEMPLATE t
  JOIN TEMPLATE_GROUP tg ON tg.tab_template_id = t.id
  JOIN GROUP g ON g.id = tg.tab_template_id  
              AND g.private != 0
  JOIN USER_GROUP ug ON ug.group_id = g.id

Way easier to read, which makes it easier to maintain.

潦草背影 2024-09-14 02:18:37

我这台机器上没有 mySql,所以我无法测试这个:

SELECT
    TT.col1,
    TT.col2,
    ...
FROM
    Tab_Templates TT
WHERE
    EXISTS
    (
        SELECT *
        FROM
            Template_Groups TG
        WHERE
            TG.tab_template_id = TT.id AND
            TG.private = 0
    ) OR
    EXISTS
    (
        SELECT *
        FROM
            User_Groups UG
        INNER JOIN Template_Groups TG2 ON
            TG2.tab_template_id = TT.id AND
            TG2.group_id = UG.group_id
        WHERE
            UG.user_id = 2
    )

I don't have mySql on this machine, so I can't test this:

SELECT
    TT.col1,
    TT.col2,
    ...
FROM
    Tab_Templates TT
WHERE
    EXISTS
    (
        SELECT *
        FROM
            Template_Groups TG
        WHERE
            TG.tab_template_id = TT.id AND
            TG.private = 0
    ) OR
    EXISTS
    (
        SELECT *
        FROM
            User_Groups UG
        INNER JOIN Template_Groups TG2 ON
            TG2.tab_template_id = TT.id AND
            TG2.group_id = UG.group_id
        WHERE
            UG.user_id = 2
    )
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文