MYSQL sorting with doctrine

有些话、适合烂在心里 提交于 2020-01-04 05:42:30

问题


as described in this question and as its answered with "Not possible" i opened a new question

so my problem goes like this : I have a table (ServiceProvider Table) each service provider have many offers (Offer table) with a OneToMany relation and each Offer have a master service (Service table) with a ManyToOne relation. What i am trying to do is to get all the service providers and their offers in an order related to serviceProvider.points and then serviceProvider.name and each service provider's offers should be ordered by their points. So for more clear view let's say i have the following

ServiceProvider
-------------------------------------------------
id      |        name     |    points    |offers|
-------------------------------------------------  
1       |        c        |      2       |1,2,3 |
-------------------------------------------------
2       |        b        |      1       |1,2   |
-------------------------------------------------
3       |        a        |      0       |1,3   |
-------------------------------------------------
ServiceOffer
-----------------------------------
id      |     name        |service|
-----------------------------------
1       |      a          |   1   |
-----------------------------------
2       |      b          |   1   |
-----------------------------------
3       |      c          |   2   |
-----------------------------------
Service
-----------------------------------
id      |    name    |    points  |
-----------------------------------
1       |      a     |      23    |
-----------------------------------
2       |      b     |      88    |
-----------------------------------

what i exactly need is a result like this

results
service_provider.name| offers.name  |
-------------------------------------
c                    |   b , a      |
-------------------------------------
b                    |   a , b      |
-------------------------------------
a                    |   b , a      |
-------------------------------------

this is the query i tried but it's not working

$query->select("sp")
            ->from("CoreBundle:ServiceProvider","sp")
            ->andWhere("sp.city = :city_name")->setParameter("city_name",$cityName)
            ->innerJoin("sp.offers","offer")
            ->innerJoin("offer.service","service","with","offer.service = service")
            ->orderBy("sp.points DESC , sp.name ASC , service.points");

needed fields

in serviceProvider

/**
* @var ServiceOffer
*
* @ORM\OneToMany(targetEntity="ServiceOffer", mappedBy="serviceProvider")
*/
private $offers;

in service

/**
* @var integer
*
* @ORM\Column(name="points", type="integer", nullable=true)
*/
private $points;

in service offer

/**
* @ORM\ManyToOne(targetEntity="Service", inversedBy="offer")
* @ORM\JoinColumn(name="service_id", referencedColumnName="id")
*
* @Serializer\Expose
* @Serializer\Groups({"service-offer", "order-entry"})
*
* @Assert\NotBlank(message="constraint.serviceOffer.service.not_blank")
*/
private $service;

回答1:


You cannot simply enumerate ORDER BY directives to Doctrine. You may give a single ->orderBy() method call, giving the field to use and direction (optional, ASC is default) as arguments, and further order fields must be add using the addOrderBy method. Your query should look like

$query->select("sp")
    ->from("CoreBundle:ServiceProvider","sp")
    ->andWhere("sp.city = :city_name")->setParameter("city_name",$cityName)
    ->innerJoin("sp.offers","offer")
    ->innerJoin("offer.service","service","with","offer.service = service")
    ->orderBy("sp.points", "DESC")
    ->addOrderBy("sp.name", "ASC")
    ->addOrderBy("service.points");

See the documentation on this topic.




回答2:


The @SolarBear 's answer is almost correct.

$query->select("sp, offer, service")
   ->from("CoreBundle:ServiceProvider","sp")
   ->andWhere("sp.city = :city_name")->setParameter("city_name",$cityName)
   ->innerJoin("sp.offers","offer")
   ->innerJoin("offer.service","service")
   ->orderBy("sp.points", "DESC")
   ->addOrderBy("sp.name", "ASC")
   ->addOrderBy("service.points","DESC");

Notice, I remove the unnecessary code in the service Inner Join. And more important, add 'DESC' string in service.points order by. It should do the trick.

Let's jump to your example :

First of all, I honestly didn't understand you map in column ServiceProvider.offers. Second, I change names of these table to be more clear to show the expected result.

ServiceProvider

-------------------------------------------------
id      |        name     |    points    |offers|
-------------------------------------------------  
1       |        C        |      2       |1,2,3 |
-------------------------------------------------
2       |        B        |      1       |1,2   |
-------------------------------------------------
3       |        A        |      0       |1,3   |
-------------------------------------------------

ServiceOffer

-----------------------------------
id      |     name        |service|
-----------------------------------
1       |      Z          |   1   |
-----------------------------------
2       |      Y          |   1   |
-----------------------------------
3       |      X          |   2   |
-----------------------------------

Service

-----------------------------------
id      |    name    |    points  |
-----------------------------------
1       |      J     |      23    |
-----------------------------------
2       |      K     |      88    |
-----------------------------------

results

ServiceProvider.name | offers.name          |       
---------------------------------------------
       C             |   X, Y, Z or X, Z, Y |  <---- I explain below
---------------------------------------------       
       B             |   Y, Z or Z, Y       |  <---- Same
---------------------------------------------
       A             |   X, Z               |
---------------------------------------------

In this example, SeviceOffer X uses Service K (points 88). While, ServiceOffer Y and Z use Service J (points 23) so there is a draw between the ServiceProvider Y and Z, so the DB can returns they in any order.

Edit

About "offers" column. Notice you mapped as a One to Many relationship. But notice, in the given table example is sound like a Many to Many. Once, ServiceProvider has many ServiceOffer and vice-versa. So for this works properly you should create a join table and removing offers column. And map in ServiceProvider a ManyToMany relationship. Such as:

Providers_Offers

------------------------------
provider_id   |   offer_id   |
------------------------------
      1       |       1      |
------------------------------
      1       |       2      |
------------------------------
      1       |       3      |
------------------------------
      2       |       1      |
------------------------------
      2       |       2      |
------------------------------
      3       |       1      |
------------------------------
      3       |       3      |


来源:https://stackoverflow.com/questions/41131139/mysql-sorting-with-doctrine

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!