5

想要最后对 Nulls 和 Blanks 进行排序,并且已经阅读了所有使用 Coalesce 函数或 If 按列排序的解决方案。

我的问题对我来说不是这些工作,因为我正在排序的列是由创建查询的 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 子句中使用函数时,我都无法使用列别名。

有什么想法可以优雅地解决这个问题吗?

4

3 回答 3

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 NULL,name 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;
于 2012-09-30T16:29:44.273 回答
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 注入。

于 2012-09-30T16:28:53.767 回答
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
于 2012-09-30T19:12:44.320 回答