最后排序Nulls

时间:2012-09-30 16:13:14

标签: mysql null sql-order-by

最后要对Nulls和Blanks进行排序,并阅读所有使用Coalesce函数或If by order by column的解决方案。

我的问题对我来说不起作用,因为我正在排序的列是由创建查询的PHP脚本动态指定的,而我的一些列在我的连接中的两个表中。

   $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";

这很好用,我可以更改变量$ sortcol,我的输出列表效果很好,除了空值和空格位于顶部。

基于其他帖子,我试过这个

   $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";

这会引发错误“ORDER BY子句中的列船不明确”。显然它需要b.boat按顺序,但由于我不会进入的原因是有问题的。 似乎无论何时我尝试在orderby子句中使用函数,我都不能使用列别名。

任何有关优雅解决方案的想法??

3 个答案:

答案 0 :(得分:4)

你是对的。我无法理解,MySQL 接受一个含糊不清的ORDER BY,只要您提供的名称不以任何方式处理(我无法做到)想到。也许其他人存在)。

一旦出现歧义,就会被拒绝。

这被接受(并且是多余的):

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

COALESCE(name, '')name IS NULLname OR NULL全部被拒绝。

显而易见的解决方案是为别名使用不同的名称,该名称不会出现在任何一个表中。

另一种可能性是创建嵌套查询:

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

那是:

$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;

答案 1 :(得分:1)

如果您有两个相似的列名,则必须在ORDER BY中指定表。就这么简单。

您应该能够在SELECT中使用其他别名来消除两个boat列的歧义,然后在

中使用该别名
$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";

注意:如果$sortcol是任何类型的用户输入的结果,则必须将其与可接受列名称的白名单进行比较,以防止SQL注入。

答案 2 :(得分:1)

根据ANSI SQL列别名(如果在ORDER BY子句中使用)只能由它们自己使用 - 您不能使用别名来投影其他列或表达式。

因此,当按列表顺序使用name并且不在表达式中时,它将被解释为对别名的引用。一旦在表达式中使用,它就无法解析为别名,因此MySQL会尝试查找要解析此问题的列。在您的查询范围内有两个这样的列,因此您会产生关于歧义的错误。

此分辨率行为可以从以下内容中看到(在MySQL和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

返回(按别名排序)

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

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

返回(按基列排序)

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