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

これは、usergroup :groupid に含まれていないすべてのユーザーを返します。ユーザーが除外されたグループに加えて他のグループのレコードを持っている場合、それらも必要ありません。

SQLクエリは機能しますが、このクエリをDQL、Doctrine for Symfony2で書く方法はありますか?

私はこれを試しました:

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

結合テーブルにまたがり、セットを台無しにするため、これは明らかに良くありません。

数学的に言えば、セットを使用して、次のようにしています: result = A\B (A にあるが B にはない要素)、A = 「すべてのユーザー」、および B = 「グループ :groupid 内のすべてのユーザー」 "。

私がやりたいことはDQLを使用して可能ですか、それともこの場合はSQLを使用する必要がありますか? 結合テーブルを独自のエンティティに変換せずに実行できますか?

テストデータ

ORM スキーマ:

  • Resources/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
    
  • Resources/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