学说区别计数
Doctrine Distinct Count
在实体集合上检索 DISTINCT COUNT
的最佳做法是什么?
在此示例实体 (Customer
) 中,我与 Orders
有 oneToMany
关系。
我想统计客户订购了多少销售额和产品:
> select * from orders;
+----------+----------+----------+
| customer | sale_ref | prod_ref |
+----------+----------+----------+
| 1 | sale_1 | prod_1 |
| 1 | sale_1 | prod_2 |
| 1 | sale_2 | prod_1 |
| 1 | sale_3 | prod_3 |
+----------+----------+----------+
> select count(prod_ref) from order where customer = 1;
+-----------------+
| count(prod_ref) |
+-----------------+
| 4 |
+-----------------+
> select count(distinct(sale_ref)) from order where customer = 1;
+-----------------+
| count(prod_ref) |
+-----------------+
| 3 |
+-----------------+
这是代码
use Doctrine\ORM\Mapping as ORM;
class Customer
{
/**
* @var \Doctrine\Common\Collections\Collection
* @ORM\OneToMany(targetEntity="Orders", mappedBy="customer", cascade={"persist", "remove"}, fetch="EXTRA_LAZY")
*/
protected $orders;
/**
* @return \Doctrine\Common\Collections\Collection
*/
public function getOrders(): \Doctrine\Common\Collections\Collection
{
return $this->orders;
}
/**
* @return int
*/
public function getOrdersProductCount(): int
{
return $this->orders->count();
}
}
class Orders
{
/**
* @var Customer $customer
* @ORM\ManyToOne(targetEntity="Customer", inversedBy="orders")
*/
protected $customer;
/**
* Non-unique sales reference
* @var string $salesRef
* @ORM\Column(name="sales_ref", type="string")
*/
protected $salesRef;
/**
* Unique product reference
* @var string $productRef
* @ORM\Column(name="product_ref", type="string")
*/
protected $productRef;
/**
* @return Customer
*/
public function getCustomer(): Customer
{
return $this->customer;
}
/**
* @return string
*/
public function getProductRef(): string
{
return $this->productRef;
}
/**
* @return string
*/
public function getSalesRef(): string
{
return $this->salesRef;
}
}
使用 Customer->getOrdersProductCount()
检索产品数量非常好,据说是 "good practice" 因为它不会在完全加载集合时访问数据库:
https://www.doctrine-project.org/projects/doctrine-orm/en/2.7/tutorials/extra-lazy-associations.html
If you mark an association as extra lazy the following methods on collections can be called without triggering a full load of the collection Collection#count()
但是,在此示例中,Customer
可以有多个产品进行销售 - 其中 salesRef
是非唯一的。检索 salesRef
的 DISTINCT COUNT
的最佳方法是什么?
这 could/should 在实体存储库中处理 class:
class OrdersRepository
{
public function getSalesCount($customer): int
{
return (int)$this->createQueryBuilder('o')
->select('COUNT(DISTINCT(o.salesRef))')
->where('o.customer = :customer')
->setParameter('customer', $customer)
->setMaxResults(1)
->getQuery()
->getSingleScalarResult();
}
public function getProductCount($customer): int
{
return (int)$this->createQueryBuilder('o')
->select('COUNT(o.productRef)')
->where('o.customer = :customer')
->setParameter('customer', $customer)
->setMaxResults(1)
->getQuery()
->getSingleScalarResult();
}
}
这有效,但我需要加载 entityManager/CustomerRepository 才能访问这些方法 - 而至少我可以从实体中检索产品计数....
我如何从客户实体中访问不同的销售计数 - 如果有的话?
我考虑过使用 Collection#filter()
method and/or looping through the Orders
entity to create an array with the salesRef
as the key and then using array_unique#count()
但这似乎没有 "right" - 我想我知道答案(使用实体存储库)但是我希望能够从 Customer
实体中访问销售计数 - 什么是最好的 practice/method?
我认为应该这样做,并且是一种更便携的方式。虽然我没有测试它。
$qb = $this->createQueryBuilder('o');
return (int)$qb
->select($qb->expr()->countDistinct('o.salesRef'))
->where('o.customer = :customer')
->setParameter('o.customer', $customer)
->setMaxResults(1)
->getQuery()
->getSingleScalarResult();
希望对您有所帮助
在实体集合上检索 DISTINCT COUNT
的最佳做法是什么?
在此示例实体 (Customer
) 中,我与 Orders
有 oneToMany
关系。
我想统计客户订购了多少销售额和产品:
> select * from orders;
+----------+----------+----------+
| customer | sale_ref | prod_ref |
+----------+----------+----------+
| 1 | sale_1 | prod_1 |
| 1 | sale_1 | prod_2 |
| 1 | sale_2 | prod_1 |
| 1 | sale_3 | prod_3 |
+----------+----------+----------+
> select count(prod_ref) from order where customer = 1;
+-----------------+
| count(prod_ref) |
+-----------------+
| 4 |
+-----------------+
> select count(distinct(sale_ref)) from order where customer = 1;
+-----------------+
| count(prod_ref) |
+-----------------+
| 3 |
+-----------------+
这是代码
use Doctrine\ORM\Mapping as ORM;
class Customer
{
/**
* @var \Doctrine\Common\Collections\Collection
* @ORM\OneToMany(targetEntity="Orders", mappedBy="customer", cascade={"persist", "remove"}, fetch="EXTRA_LAZY")
*/
protected $orders;
/**
* @return \Doctrine\Common\Collections\Collection
*/
public function getOrders(): \Doctrine\Common\Collections\Collection
{
return $this->orders;
}
/**
* @return int
*/
public function getOrdersProductCount(): int
{
return $this->orders->count();
}
}
class Orders
{
/**
* @var Customer $customer
* @ORM\ManyToOne(targetEntity="Customer", inversedBy="orders")
*/
protected $customer;
/**
* Non-unique sales reference
* @var string $salesRef
* @ORM\Column(name="sales_ref", type="string")
*/
protected $salesRef;
/**
* Unique product reference
* @var string $productRef
* @ORM\Column(name="product_ref", type="string")
*/
protected $productRef;
/**
* @return Customer
*/
public function getCustomer(): Customer
{
return $this->customer;
}
/**
* @return string
*/
public function getProductRef(): string
{
return $this->productRef;
}
/**
* @return string
*/
public function getSalesRef(): string
{
return $this->salesRef;
}
}
使用 Customer->getOrdersProductCount()
检索产品数量非常好,据说是 "good practice" 因为它不会在完全加载集合时访问数据库:
https://www.doctrine-project.org/projects/doctrine-orm/en/2.7/tutorials/extra-lazy-associations.html
If you mark an association as extra lazy the following methods on collections can be called without triggering a full load of the collection
Collection#count()
但是,在此示例中,Customer
可以有多个产品进行销售 - 其中 salesRef
是非唯一的。检索 salesRef
的 DISTINCT COUNT
的最佳方法是什么?
这 could/should 在实体存储库中处理 class:
class OrdersRepository
{
public function getSalesCount($customer): int
{
return (int)$this->createQueryBuilder('o')
->select('COUNT(DISTINCT(o.salesRef))')
->where('o.customer = :customer')
->setParameter('customer', $customer)
->setMaxResults(1)
->getQuery()
->getSingleScalarResult();
}
public function getProductCount($customer): int
{
return (int)$this->createQueryBuilder('o')
->select('COUNT(o.productRef)')
->where('o.customer = :customer')
->setParameter('customer', $customer)
->setMaxResults(1)
->getQuery()
->getSingleScalarResult();
}
}
这有效,但我需要加载 entityManager/CustomerRepository 才能访问这些方法 - 而至少我可以从实体中检索产品计数....
我如何从客户实体中访问不同的销售计数 - 如果有的话?
我考虑过使用 Collection#filter()
method and/or looping through the Orders
entity to create an array with the salesRef
as the key and then using array_unique#count()
但这似乎没有 "right" - 我想我知道答案(使用实体存储库)但是我希望能够从 Customer
实体中访问销售计数 - 什么是最好的 practice/method?
我认为应该这样做,并且是一种更便携的方式。虽然我没有测试它。
$qb = $this->createQueryBuilder('o');
return (int)$qb
->select($qb->expr()->countDistinct('o.salesRef'))
->where('o.customer = :customer')
->setParameter('o.customer', $customer)
->setMaxResults(1)
->getQuery()
->getSingleScalarResult();
希望对您有所帮助