【问题标题】:filter table based on join but select all joins without taking filter into account基于连接过滤表,但选择所有连接而不考虑过滤
【发布时间】:2021-12-19 20:20:21
【问题描述】:

我使用 Typeorm 查询构建器生成了以下查询

当前行为: 现在发生的事情是海军陆战队被正确过滤,但选定的连接也被给定条件过滤。只返回符合条件的码头,而不是所有属于海军陆战队的码头。

期望的结果: 我想获得至少拥有一个名为“dock 1”的码头的所有海军陆战队员。我想包括属于该海军陆战队的所有码头,而不考虑他们的名字。

我应该如何执行这个查询?

任何帮助将不胜感激。

mariadb 版本 15.1

typeorm@0.2.37

SELECT `c`.`id`                AS `c_id`,
       `c`.`name`              AS `c_name`,
       `c`.`description`       AS `c_description`,
       `c`.`FkId`              AS `c_FkId`,
       `c`.`FkModel`           AS `c_FkModel`,
       `c`.`isActive`          AS `c_isActive`,
       `c`.`createdAt`         AS `c_createdAt`,
       `c`.`updatedAt`         AS `c_updatedAt`,
       `c`.`phones`            AS `c_phones`,
       `c`.`emails`            AS `c_emails`,
       `c`.`mainImage`         AS `c_mainImage`,
       `c`.`galleryImages`     AS `c_galleryImages`,
       `c`.`addressDetailsId`  AS `c_addressDetailsId`,
       `c_Docks`.`id`          AS `c_Docks_id`,
       `c_Docks`.`name`        AS `c_Docks_name`,
       `c_Docks`.`description` AS `c_Docks_description`,
       `c_Docks`.`FkId`        AS `c_Docks_FkId`,
       `c_Docks`.`FkModel`     AS `c_Docks_FkModel`,
       `c_Docks`.`isActive`    AS `c_Docks_isActive`,
       `c_Docks`.`createdAt`   AS `c_Docks_createdAt`,
       `c_Docks`.`updatedAt`   AS `c_Docks_updatedAt`,
       `c_Docks`.`MarineId`    AS `c_Docks_MarineId`
FROM `marine` `c`
         LEFT JOIN `dock` `c_Docks` ON `c_Docks`.`MarineId` = `c`.`id`
WHERE `c`.`isActive` = true
  AND (`c_Docks`.`name` = 'dock 1')
# ORDER BY c_id DESC

【问题讨论】:

    标签: mysql sql mariadb typeorm


    【解决方案1】:

    您可以通过dock 加入两次。一次过滤码头名称,另一次获取所有码头。

    SELECT `c`.`id`                AS `c_id`,
           `c`.`name`              AS `c_name`,
           `c`.`description`       AS `c_description`,
           `c`.`FkId`              AS `c_FkId`,
           `c`.`FkModel`           AS `c_FkModel`,
           `c`.`isActive`          AS `c_isActive`,
           `c`.`createdAt`         AS `c_createdAt`,
           `c`.`updatedAt`         AS `c_updatedAt`,
           `c`.`phones`            AS `c_phones`,
           `c`.`emails`            AS `c_emails`,
           `c`.`mainImage`         AS `c_mainImage`,
           `c`.`galleryImages`     AS `c_galleryImages`,
           `c`.`addressDetailsId`  AS `c_addressDetailsId`,
           `c_Docks`.`id`          AS `c_Docks_id`,
           `c_Docks`.`name`        AS `c_Docks_name`,
           `c_Docks`.`description` AS `c_Docks_description`,
           `c_Docks`.`FkId`        AS `c_Docks_FkId`,
           `c_Docks`.`FkModel`     AS `c_Docks_FkModel`,
           `c_Docks`.`isActive`    AS `c_Docks_isActive`,
           `c_Docks`.`createdAt`   AS `c_Docks_createdAt`,
           `c_Docks`.`updatedAt`   AS `c_Docks_updatedAt`,
           `c_Docks`.`MarineId`    AS `c_Docks_MarineId`
    FROM `marine` `c`
    JOIN `dock` `c_Docks` ON `c_Docks`.`MarineId` = `c`.`id`
    JOIN `dock` `dock_1` ON `dock_1`.`MarineId` = `c`.`id`
    WHERE `c`.`isActive` = true
      AND `dock_1`.`name` = 'dock 1'
    

    这里没有理由使用LEFT JOIN,因为您不想包含没有匹配dock 的海军陆战队员。

    【讨论】:

    • 这在性能方面与其他解决方案相比如何
    • 此查询是由请求动态生成的,在这种情况下,过滤器和连接关系是相同的,但并非总是如此。即使没有匹配的码头,我也想包括海军陆战队。
    • 应该会更好,因为INNER JOIN 通常比OUTER JOIN 快。
    • 你写了“我想获得所有至少有一个码头名称为'dock 1'的海军陆战队员”如果他们没有任何匹配项,他们怎么能拥有至少一个名称为'dock 1'的码头码头?
    • 对不起,我没有很好地解释自己。我处理的请求的一部分是根据某些标准过滤实体,第二部分是加入请求的关系。这个问题是基于这两个任务相互冲突的场景。我确实使用内部连接进行过滤,但不用于加载请求的关系。
    【解决方案2】:

    第 1 步:从表 Marine 中过滤掉所有相关的行: 从海洋 C 中选择 c.isActive = true
    第 2 步:使前面的 SQL 成为内联视图,并将其与表停靠区连接并在停靠表上应用过滤器。 所以,SQL 应该是这样的:

    SELECT          c.<column_names> ,
                    c_docks.<column_names>
    FROM            (
                           SELECT <column_names>
                           FROM   marine
                           WHERE  isActive = true) c
    LEFT OUTER JOIN dock c_docks
    ON              c.id = c_docks.marine_id
    AND             c_docks.NAME = 'dock 1';
    

    【讨论】:

    • 非常感谢它非常接近我想要的。
    • 为什么使用LEFT OUTER JOIN
    猜你喜欢
    • 1970-01-01
    • 2012-12-26
    • 1970-01-01
    • 2010-10-13
    • 2017-11-30
    • 1970-01-01
    • 2022-08-24
    • 1970-01-01
    • 2021-02-24
    相关资源
    最近更新 更多