How can I order by NULL in DQL?

后端 未结 6 725
野趣味
野趣味 2021-01-02 20:18

I\'m building an app using Symfony2 framework and using Doctrine ORM. I have a table with airlines for which some IATA codes are missing. I\'m outputting a list, ordered by

6条回答
  •  野趣味
    野趣味 (楼主)
    2021-01-02 20:34

    By default, MySQL will still sort a NULL value; it will just place it at the beginning of the result set if it was sorted ASC, and at the end if it was sorted DESC. Here, you're looking to sort ASC, but you want the NULL values to be at the bottom.

    Unfortunately, as powerful as it is, Doctrine isn't going to offer much support here, since function support is limited, and most of it is limited to SELECT, WHERE, and HAVING clauses. You actually wouldn't have a problem at all if any of the following were true about the QueryBuilder:

    • select() accepted ISNULL()
    • orderBy() or addOrderBy() supported ISNULL()
    • the class supported the concept of UNIONs (with this, you could run two queries: one where the codeIata was NULL, and one where it wasn't, and you could sort each independently)

    So that said, you can go with the user-defined functions that ArtWorkAD mentioned already, or you could replicate that last point with two different Doctrine queries:

    $airlinesWithCode = $er->createQueryBuilder("airline")
        ->where("airline.iataCode IS NULL")
        ->getQuery()
        ->getResult();
    $airlinesWithoutCode = $er->createQueryBuilder("airline")
        ->where("airline.iataCode IS NOT NULL")
        ->getQuery()
        ->getResult();
    

    Then you can combine these into a single array, or treat them independently in your templates.

    Another idea is to have DQL return everything in one data set, and let PHP do the heavy lifting. Something like:

    $airlines = $er->findAll();
    $sortedAirlines = array();
    // Add non-NULL values to the end if the sorted array
    foreach ($airlines as $airline)
        if ($airline->getCodeIata())
            $sortedAirlines[] = $airline;
    // Add NULL values to the end of the sorted array
    foreach ($airlines as $airline)
        if (!$airline->getCodeIata())
            $sortedAirlines[] = $airline;
    

    The downside to both of these is that you won't be able to do LIMITs in MySQL, so it might only work well for relatively small data sets.

    Anyway, hope this gets you on your way!

提交回复
热议问题