2013-07-01 1 views
0

У меня есть следующий SQL-запрос:Доктрина DQL LEFT JOIN установить разницу

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, 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 для этого случая? Можно ли это сделать, не превращая таблицы соединений в собственные?

Тестовые данные

ОРМ схемы:

  • Ресурсы/конфигурации/Доктрина/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 
    
  • Ресурсы/конфигурации/Доктрина/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); 

ответ

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 
    ) 

Похоже, что он делает правильно, тоже.

Это один из тех ответов, которые один находит случайно, просто после проводка StackOverflow после ничего не найдя с помощью поиска Google и StackOverflow в течение нескольких дней :)

Fun Fact: Вы можете» t запустить этот DQL в Symfony2 ./app/console с doctrine: query: dql - по крайней мере, это дает мне ошибку, когда я пытаюсь заменить: group с идентификатором.