2015-02-10 6 views
3

Моя сущность (Продукт) имеет однонаправленное отношение многого к другому объекту (компании) под названием deletedByCompanies.Выделить сущности, предполагающие связанную сущность, не существует

Я хочу выбрать все продукты, которые не были удалены определенной компанией. Это все продукты, которые не связаны этим отношением многих-многих.

Пробовал:

$this->em->getRepository(Product::class)->createQueryBuilder('t') 
->leftJoin('t.deletedByCompanies', 'deletedCompany') 
->andWhere('deletedCompany.id not in (:companyId)') 
->setParameter('companyId', [$companyId]); 

Но это просто не возвращает ничего. Схема довольно straghtforward:

Product: 
    id: int PK 

Company: 
    id: int PK 

DeletedProducts 
    product_id: int FK 
    company_id: int FK 

определение сущностей в классе продукта:

/** 
* @var Company[] 
* @ORM\ManyToMany(targetEntity="Company", indexBy="id") 
* @ORM\JoinTable(name="DeletedProducts") 
*/ 
protected $deletedByCompanies; 
+0

* «Я хочу выбрать все продукты, которые не были удалены определенной компанией». *. Вы имеете в виду только ** удаленные ** продукты, которые не были удалены этой компанией? Или все продукты, в том числе не удаленные вообще? – axiac

+0

Показать структуру таблиц (имена таблиц и имена полей идентификатора). – axiac

+0

Только НЕ УДАЛЕННЫЕ продукты Компании. –

ответ

3

Я думаю, вы можете решить вашу проблему с помощью предложения NOT EXISTS на удаленной таблице.

В SQL диалекта:

SELECT * FROM product p WHERE NOT EXISTS 
(SELECT * FROM DeletedProducts d WHERE p.id=d.product_id AND company_id = 2); 

В Doctrine2 DQL, мы не имеем сущность DeletedProducts поэтому мы должны сделать немного больше такие вещи, как:

$qb = $this->em->getRepository("AcmeDemoBundle:Product")->createQueryBuilder('t') 
    ->Join('t.deletedByCompanies', 'deletedCompany') 
    ->andWhere('deletedCompany.id in (:companyId)') 
    ->andWhere("p=t"); 

$mainQb = $this->em->getRepository("AcmeDemoBundle:Product")->createQueryBuilder('p'); 
$mainQb->where($mainQb->expr()->not($mainQb->expr()->exists($qb->getDQL()))); 
$mainQb->setParameter('companyId', [$companyId]); 

var_dump($mainQb->getQuery()->getSql()); 
$res =$mainQb->getQuery()->execute(); 

Позвольте мне знать, если Я не понимаю вашу проблему.

Надеюсь, что эта помощь

+0

Если вы хотите повторно использовать этот код, создайте пользовательский класс репозитория ... http://symfony.com/doc/current/book/doctrine.html#custom-repository-classes –

+0

Спасибо @GuilhermeViebig, конечно! Этот метод должен находиться в пользовательском методе репозитория! BTW является лишь примером для преобразования запроса в стиле DNL, ​​поэтому я не рассматриваю этот аспект, надеюсь, что Майк немного переработает и позаботится о ваших комментариях! Еще раз спасибо! – Matteo

2

Я не знаком с доктриной, но я стараюсь, чтобы помочь с некоторыми SQL знаний. После запрос должен делать то, что вы хотите:

SELECT DISTINCT Product.* FROM Product 
LEFT JOIN DeletedProducts on product_id = product.id 
WHERE product_id IS NULL OR product_id != 
    ALL(SELECT product_id FROM DeletedProducts WHERE company_id = 2) 

Некоторые Разъяснение ...

DISTINCT: Nessacary ключевого слова, чтобы предотвратить дублирование. Один и тот же продукт может появляться несколько раз в результате Left Join, если он удален. DISTINCT устраняет эти дубликаты.

WHERE product_id IS NULL:Left Регистрация также список продуктов, которые не связаны с какой-либо компании над «DeletedProducts» -стол. Поскольку нет никаких отношений, поля product_id и company_id являются NULL.

OR product_id! = ALL ([...]): Теперь, когда у нас есть продукты, которые не удаляются какой-либо компанией, нам необходимы дополнительные, которые не удаляются определенной компанией. Поэтому мы используем ИЛИ с подзапросом, который выбирает все удаленные продукты определенной компании (например, id = 2 компании, как в примере кода). Поскольку мы хотим иметь не-удаленные продукты, мы должны использовать оператор «! =» -.

Надеюсь, это немного поможет. Теперь вам нужно «перевести» запрос на использование в Doctrine.

+0

Хорошо, теперь это должно быть сделано. Я сделал запрос низкого уровня, чтобы получить идентификатор записи, который я хочу выбрать. Затем выбор чистой доктрины основывался на простых критериях «ID in (...)». Благодарю. –

Смежные вопросы