В приложении Symfony 3.4 у меня есть сущность с 4 свойствами плюс идентификатор.

Это управляется доктриной базы данных mySql.

Назовите свойства с именами p1, p2, p3 и q. Пример таблицы БД может быть такой:

id  p1  p2  p3  q
------------------
1   x   y   z   1
2   x   y   n   2
3   x       z   1
4   x       z   2
5   x   y   z   3
6   x   y   z   4
7   x   n   z   1

Что мне нужно сделать, так это запросить все сущности из БД, которые имеют разные комбинации p1, p2, p3. Итак, используя данную таблицу образцов БД, результат, который мне нужен, будет

id  p1  p2  p3  q
------------------
1   x   y   z   1
2   x   y   n   2
3   x       z   1
7   x   n   z   1

Таким образом, строки с идентификаторами 4, 5 и 6 не будут в наборе, потому что они имеют «удвоенные» комбинации p1, p2, p3.

Теперь - как мне это сделать, используя методы класса Repository в Symfony 3.4, как описано здесь:

https://symfony.com/doc/3.4/doctrine.html

Или есть другие способы достичь того, что я ищу?

Любые подсказки приветствуются.

< Сильный > EDIT : В основном я ищу список всех существующих комбинаций p1, p2, p3 без удвоения комбинации в списке. Не имеет значения, какая строка возвращается в результирующем наборе (в отношении свойств id и q), если включена одна (и только одна) строка каждой комбинации p1, p2, p3.

1
user3440145 23 Окт 2018 в 18:39

2 ответа

Лучший ответ

Если вам нужна только другая уникальная комбинация p1, p2 и p3 и вас не интересуют id и q, вы можете исключить их из своего запрос и использование отдельного предложения.

Для ваших нужд встроенного метода класса Repository нет, вы можете создать настраиваемый класс репозитория (я лично делаю это каждый раз, когда мне нужно писать собственные запросы для моих сущностей)

Рассмотрим вашу сущность (в примере в src/AppBundle/Entity/MyEntity.php) объявленную таким образом:

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="AppBundle\Repository\MyEntityRepository")
 */
class MyEntity
{
    //declarations of $id, $p1 and so on...
}

Вы можете создать собственный класс репозитория (в примере src/AppBundle/Repository/MyEntityRepository.php) с методом для получения необходимого результата:

namespace AppBundle\Repository;

use Doctrine\ORM\EntityRepository;

class MyEntityRepository extends EntityRepository
{
    public function findAllUniqueCombinations()
    {
        $result = $this->createQueryBuilder('m')
                       ->select('m.p1 p1', 'm.p2 p2', 'm.p3 p3')
                       ->distinct()
                       ->getQuery()
                       ->getResult();

        return ($result);
    }
}

И в некоторых действиях контроллера:

$MyCombinationList = $this->getDoctrine()
                          ->getManager()
                          ->getRepository(MyEntity::class)
                          ->findAllUniqueCombinations();

Я использовал тот же запрос для тестирования (изменился только select())

Входные данные

id | name       | firstname
---+------------+---------- 
 1 | Smith      | John 
 2 | Smith      | John 
 3 | Smith      | John 
 4 | Smith      | John 
 5 | Doe        | Jane 
 6 | Connor     | Sarah 
 7 | The Sponge | Bob 
 8 | Marley     | Bob

Выбор был ->select('c.name name', 'c.firstname firstname')

Результат var_dump($result); дал:

array (size=5)
  0 => 
    array (size=2)
      'name' => string 'Smith' (length=5)
      'firstname' => string 'John' (length=4)
  1 => 
    array (size=2)
      'name' => string 'Doe' (length=3)
      'firstname' => string 'Jane' (length=4)
  2 => 
    array (size=2)
      'name' => string 'Connor' (length=6)
      'firstname' => string 'Sarah' (length=5)
  3 => 
    array (size=2)
      'name' => string 'The Sponge' (length=9)
      'firstname' => string 'Bob' (length=3)
  4 => 
    array (size=2)
      'name' => string 'Marley' (length=6)
      'firstname' => string 'Bob' (length=3)
1
Cid 23 Окт 2018 в 17:19

Подзапрос "группировать по" для удаления повторяющихся данных и основной запрос для поиска по идентификаторам:

$dql = 'SELECT r FROM myTable r
WHERE r.id IN (
    SELECT min(s.id) FROM myTable s
    GROUP BY s.p1, s.p2, s.p3
)';

$rows = $em->createQuery($dql)
    ->getResult();
2
Guillaume 23 Окт 2018 в 16:29
52952953