0

我有以下 SQL 查询:

SELECT DISTINCT u.id
    FROM User u
    LEFT JOIN usergroup_user ug1 ON u.id = ug1.user_id
    LEFT JOIN usergroup_user ug2 ON ug1.user_id = ug2.user_id AND ug2.usergroup_id = :groupid
    WHERE ug2.usergroup_id IS NULL

这样做是返回所有不在用户组:groupid 中的用户。如果用户除了排除的组之外还有其他组的记录,我也不想要这些。

SQL 查询有效,但有没有办法在 DQL、Symfony2 的 Doctrine 中编写这个查询?

我试过这个:

SELECT DISTINCT u.id
    FROM AcmeDemoBundle:User u
    LEFT JOIN u.groups ug1
    LEFT JOIN u.groups ug2 WITH ug1 = ug2 AND ug2 = :groupid
    WHERE ug2 IS NULL

但它不起作用。DQL 语句被翻译成以下 SQL 语句:

SELECT DISTINCT u0_.id AS id0
    FROM User u0_
    LEFT JOIN usergroup_user u2_ ON u0_.id = u2_.user_id
    LEFT JOIN UserGroup u1_ ON u1_.id = u2_.usergroup_id
    LEFT JOIN usergroup_user u4_ ON u0_.id = u4_.user_id
    LEFT JOIN UserGroup u3_ ON u3_.id = u4_.usergroup_id AND (u1_.id = u3_.id AND u3_.id = :groupid)
    WHERE u3_.id IS NULL

这显然不好,因为它跨越了连接表并弄乱了集合。

用数学术语来说,使用集合,我这样做:结果 = A\B(在 A 中但不在 B 中的元素),A =“所有用户”,B =“组中的所有用户:groupid ”。

我想用 DQL 做些什么,还是应该只使用 SQL 来处理这种情况?可以在不将连接表变成它们自己的实体的情况下完成吗?

测试数据

ORM 架构:

  • 资源/config/doctrine/User.orm.yml

    Acme\DemoBundle\Entity\User:
      type: entity
      table: null
      fields:
        id:
          type: integer
          id: true
          generator:
            strategy: AUTO
      manyToMany:
        groups:
          targetEntity: UserGroup
          mappedBy: users
    
  • 资源/config/doctrine/UserGroup.orm.yml

    Acme\DemoBundle\Entity\UserGroup:
      type: entity
      table: null
      fields:
        id:
          type: integer
          id: true
          generator:
            strategy: AUTO
      manyToMany:
        users:
          targetEntity: User
          inversedBy: groups
    

SQL 数据:

INSERT INTO `User` VALUES (1),(2),(3),(4);
INSERT INTO `UserGroup` VALUES (1),(2),(3),(4);
INSERT INTO `usergroup_user` VALUES (1,1),(1,2),(1,3),(2,2),(3,4);
4

1 回答 1

1

我想我在发布后就在侧边栏中的“相关”链接中找到了答案,该链接在MEMBER OF可能不相关的上下文中提到。

我的 DQL 现在看起来像这样:

SELECT DISTINCT u.id
    FROM AcmeDemoBundle:User u
    WHERE :group NOT MEMBER OF u.groups

这意味着:

SELECT DISTINCT u0_.id AS id0
    FROM User u0_
    WHERE NOT EXISTS (
        SELECT 1
        FROM usergroup_user u1_
        INNER JOIN UserGroup u2_ ON u1_.usergroup_id = u2_.id
        WHERE u1_.user_id = u0_.id AND u2_.id = :group
    )

看起来它也在做正确的事情。

这是人们偶然发现的答案之一,在通过搜索 Google 和 StackOverflow 几天后未找到任何内容后发布到 StackOverflow :)

有趣的事实:你不能在 Symfony2 的 ./app/console 中使用教义:查询:dql 运行这个 DQL - 至少当我尝试用 ID 替换 :group 时它给了我一个错误。

于 2013-07-01T19:46:27.037 回答