Sorting Nulls last

会有一股神秘感。 提交于 2019-12-21 15:08:56

问题


Want to sort Nulls and Blanks last and have read all the solutions that use either the Coalesce function or the If in the order by column.

MY problems is non of these work for me because the column I am sorting on is specified dynamically by the PHP script that creates the query and some of my columns are in two tables in my join.

   $sortcol="boat";
   $sql= "SELECT fleet,b.boat as boat,owner FROM boats as b 
   LEFT JOIN owners as o ON  b.boat=o.boat 
   ORDER BY $sortcol";

This works great, I can change the variable $sortcol and my output listing works great except the nulls and blanks are at the top.

Based on other postings I tried this

   $sortcol="boat";
   $sql= "SELECT fleet,b.boat as boat,owner FROM boats as b 
   LEFT JOIN owners as o ON  b.boat=o.boat 
   ORDER BY IF($sortcol is NULL,1,0), $sortcol";

This throws the error "column boat in ORDER BY clause is ambiguous". Obviously it wants b.boat in the order by, but for reasons I won't get into that is problematic. It appears that anytime I try to use a function in the orderby clause I can't use the column alias.

Any ideas for an elegant solution to this??


回答1:


You're right. For no reason that I can fathom, MySQL accepts an ambiguous ORDER BY as long as the name you supply is not handled in any way (no way that I could think of. Maybe others exist).

As soon as it is, ambiguousness gets rejected.

This is accepted (and redundant):

select b.id, a.name as name
    FROM client AS a JOIN client AS b ON (a.id = b.id)
    ORDER BY name, name;

while COALESCE(name, ''), name IS NULL, name OR NULL are all rejected.

The obvious solution is to use a different name for the alias, one that does not appear in either table.

Another possibility would be to create a nested query:

SELECT * FROM ( your query here, without ORDER ) AS original
ORDER BY IF($sortcol is NULL,1,0), $sortcol;

That is:

$sortcol="boat";
$sql = <<<SQL
   SELECT * FROM (
      SELECT fleet,b.boat as boat,owner FROM boats as b 
         LEFT JOIN owners as o ON  b.boat=o.boat 
   ) AS original
   ORDER BY IF($sortcol is NULL,1,0), $sortcol;
SQL;



回答2:


You MUST specify the table in the ORDER BY if you have two similar column names. It's that simple.

You should be able to use a different alias in the SELECT which disambiguates from both boat columns and then use that in the

$sortcol = "bboat";
$sql= "
  SELECT 
    fleet,
    /* Alias as bboat to disambiguate from b.boat and o.boat
    b.boat as bboat,
    owner 
  FROM 
    boats as b
    LEFT JOIN owners as o ON  b.boat=o.boat 
  ORDER BY IF($sortcol is NULL,1,0), $sortcol";

Note: if $sortcol is the result of any kind of user input, it is necessary to compare it against a whitelist of acceptable column names to prevent SQL injection.




回答3:


According to ANSI SQL column aliases if used in the ORDER BY clause can only be used by themselves - you can't use the aliases to project other columns or expressions.

So when name is used in the order by list and is not in an expression it is interpreted as a reference to the alias. Once used in an expression then it can't resolve to an alias so MySQL tries to find a column to resolve this to. There are two such columns in scope in your query hence the error you get about ambiguity.

This resolution behavior can be seen from the following (tested in MySQL and SQL Server)

CREATE TABLE T
(
C INT,
D INT
)

INSERT INTO T
SELECT 1, 2 UNION ALL
SELECT 2, 1

SELECT C AS D, D AS C
FROM T 
ORDER BY D

Returns (ordered by alias)

D           C
----------- -----------
1           2
2           1

SELECT C AS D, D AS C
FROM T 
ORDER BY D + 0

Returns (ordered by base column)

D           C
----------- -----------
2           1
1           2


来源:https://stackoverflow.com/questions/12662780/sorting-nulls-last

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