2015-02-10 58 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 2015-02-12 16:18:50

+0

显示表格结构(表格名称和ID字段名称)。 – axiac 2015-02-12 16:19:47

+0

只有公司的NOT DELETED产品。 – 2015-02-12 17:11:23

回答

3

我认为你可以用deleby表上的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 – 2015-02-18 14:47:50

+0

谢谢@GuilhermeViebig,当然!此方法必须驻留在自定义存储库方法中!顺便说一句,这只是一个DNL风格的查询转换的例子,所以我没有涉及这方面,我希望迈克能做一点重构,并照顾你的意见!再次感谢! – Matteo 2015-02-18 14:50:15

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关键字,以防止冗余。如果左连接被删除,同一产品可能会出现多次。 DISTINCT消除了这些重复项。

WHERE的product_id IS NULL:左连接也将列出未在“DeletedProducts” - 表相关的任何一家公司的产品。由于没有关系,所以字段product_idcompany_idNULL

或product_id!= ALL([...]):现在我们已经获得了未被任何公司删除的产品,我们还需要那些未被特定公司删除的产品。因此,我们使用以及选择某个公司的所有删除产品(例如,如代码示例中的公司id = 2)的子查询。由于我们希望拥有未删除的产品,因此我们必须使用“!=” - 运算符。

我希望这会有所帮助。现在,您需要在Doctrine中“翻译”查询用法。

+0

好吧,现在必须做。我做了一个低级别的查询来获得我想选择的记录ID。然后,纯粹的学说选择基于简单的“ID in(...)”标准。谢谢。 – 2015-02-13 08:45:00