postgres` order by`参数类型

时间:2016-01-30 10:15:38

标签: postgresql sql-order-by

Postgresql中<?php $dbname = "mytest"; $servername = "***"; $username = "mohsen"; $passwords = "****"; // Create connection $conn = new mysqli($servername, $username, $passwords, $dbname); // Check connection if ($conn->connect_error) { die("Connection failed: " . $conn->connect_error); } $User=$_POST['username']; $sql="SELECT * FROM Money WHERE Debtor='$User' OR Creditor='$User' "; $result = $conn->query($sql); // while($field=mysql_fetch_assoc($result)) { print $field["Debtor"]."|"; print $field["Creditor"]."|"; print $field["Cost"]."|"; print $field["Status"]."|"."\n"; } $conn->close(); ?> 子句的参数类型是什么?

我遇到了一个非常奇怪的行为(使用Postgresql 9.5)。即,查询

order by

按预期生成select * from unnest(array[1,4,3,2]) as x order by 1; 。但是查询

1,2,3,4

产生select * from unnest(array[1,4,3,2]) as x order by 1::int; ,这看起来很奇怪。同样,每当我用任何函数(例如1,4,3,2)或1::int运算符替换greatest(0,1)时,结果都是无序的(与what I would expect相反)。

case的参数应该具有哪种类型,以及如何获得预期的行为?

3 个答案:

答案 0 :(得分:3)

这是预期的(and documented)行为:

  

A sort_expression也可以是列标签或输出列的编号

所以表达式:

order by 1

按结果集的第一列(由SQL标准定义)

进行排序

然而表达式:

order by 1::int

按常量值1排序,它基本上与:

相同
order by 'foo'

通过对order by使用常量值,所有行都具有相同的排序值,因此不会真正排序。

要按表达式排序,只需使用:

order by 
    case 
       when some_column = 'foo' then 1
       when some_column = 'bar' then 2
       else 3
    end

以上内容根据case表达式的结果对结果进行排序。

答案 1 :(得分:1)

  

实际上我有一个带整数参数的函数,它指示要在order by子句中使用的列。

如果所有列的类型相同,则可以这样做:

SELECT ....
ORDER BY 
  CASE function_to_get_a_column_number()
    WHEN 1 THEN column1
    WHEN 2 THEN column2
    .....
    WHEN 1235 THEN column1235
END

如果列的类型不同,您可以尝试:

SELECT ....
ORDER BY 
  CASE function_to_get_a_column_number()
    WHEN 1 THEN column1::varchar
    WHEN 2 THEN column2::varchar
    .....
    WHEN 1235 THEN column1235::varchar
END

但这些&#34;变通办法&#34;很可怕除了返回列号的函数之外,还需要一些其他方法。 也许是动态SQL?

答案 2 :(得分:0)

我想说动态SQL(感谢@kordirko和其他提示)是我最初想到的问题的最佳解决方案:

create temp table my_data (
  id serial,
  val text
);

insert into my_data(id, val)
values (default, 'a'), (default, 'c'), (default, 'd'), (default, 'b');

create function fetch_my_data(col text)
returns setof my_data as
$f$
begin
 return query execute $$
   select * from my_data
   order by $$|| quote_ident(col);
end
$f$ language plpgsql;

select * from fetch_my_data('val'); -- order by val
select * from fetch_my_data('id'); -- order by id

一开始我认为可以使用order by子句的参数中的case表达式来实现这一点 - sort_expression。这里有一个让我困惑的棘手部分:当sort_expression一种标识符(列名或列数)时,在排序结果时会使用相应的列。但是当sort_expression 某个值时,我们实际上使用该值本身(为每一行计算)对结果进行排序。这是@ a_horse_with_no_name的回答。

因此,当我查询... order by 1::int时,我已经为每行指定了值1,然后尝试对一组数组进行排序,这显然没用。

some workarounds without dynamic queries,但它们需要编写更多代码,似乎没有任何明显的优势。