我的实体(产品)与另一个名为 deletedByCompanies 的实体(公司)有多方向的单向关系。
我希望选择尚未被特定公司删除的所有产品。这就是所有通过这么多关系没有联系的产品。
尝试:
$this->em->getRepository(Product::class)->createQueryBuilder('t')
->leftJoin('t.deletedByCompanies', 'deletedCompany')
->andWhere('deletedCompany.id not in (:companyId)')
->setParameter('companyId', [$companyId]);
但这根本不会返回任何东西。 架构很简单:
Product:
id: int PK
Company:
id: int PK
DeletedProducts
product_id: int FK
company_id: int FK
Product class中的实体定义:
/**
* @var Company[]
* @ORM\ManyToMany(targetEntity="Company", indexBy="id")
* @ORM\JoinTable(name="DeletedProducts")
*/
protected $deletedByCompanies;
答案 0 :(得分:3)
我认为您可以使用deletedby表上的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();
如果我不明白你的问题,请告诉我。
希望这个帮助
答案 1 :(得分:2)
我不熟悉Doctrine,但我正在努力帮助学习一些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为空: 左连接还将列出与“DeletedProducts”-table相关的任何公司无关的产品。由于没有关系,字段 product_id 和 company_id 是 NULL 。
OR product_id!= ALL([...]):现在我们已经获得了未被任何公司删除的产品,我们还需要那些未被删除的产品特别的公司。因此,我们使用带有子查询的 OR ,该子查询选择某个公司的所有已删除产品(例如公司ID = 2,如代码示例中所示)。由于我们希望拥有未删除的产品,因此我们必须使用“!=” - 运营商。
我希望这会有所帮助。现在由您来“翻译”Doctrine中的用法查询。