【问题标题】:Postgresql : select distinct * from func() ;Postgresql : select distinct * from func() ;
【发布时间】:2019-12-26 02:36:28
【问题描述】:
----------------     PostgreSQL:    ---------------------

drop table if exists test;
CREATE TABLE test
(
"Id" SERIAL NOT NULL,
"User" VARCHAR(64) NOT NULL,
"Name" VARCHAR(50) NOT NULL,
"DId" INTEGER NOT NULL,
PRIMARY KEY("User"));
----------------- CREATE  TABLE ---------------------


truncate table test;

insert into test values
(1655,'1000000000','1000000000',6),
(844,'111','111',6),
(847,'114','114',6),
(849,'116','116',6),
(864,'131','131',6),
(884,'151','151',6),
(3242,'201919-11:29:3:340','sizhanerLD',6),
(3241,'201919-11:28:17:506','sizhanerZB',6),
(3240,'201919-11:27:37:15','sizhanerLD',6),
(3239,'201919-11:25:57:629','sizhanerZB',6);
----------------- INSERT  DATA ----------------------

create TYPE "public"."BPI" as (
        "Id" integer,
        "DId"   integer,
        "User"  VARCHAR(64), 
        "Name"  VARCHAR(50) 
);

---------------------------------CREATE TYPE --------------------------------------------------




--------------CREATE 3 FUNC()-----------------

CREATE OR REPLACE FUNCTION "QBP_1"()
RETURNS TABLE("Item" "BPI")
AS $$
declare
    "MyCsr" refcursor;
     "SqlStr" varchar(10240) := 'SELECT "Id", "DId", "User", "Name" from test ORDER BY "Name" ASC LIMIT 10 OFFSET 0';
BEGIN
    raise notice 'SQL :%', "SqlStr";
    open "MyCsr" for EXECUTE "SqlStr";   
     fetch "MyCsr" into "Item";
     while FOUND loop
        return next;
        fetch "MyCsr" into "Item";
     end loop;
     close "MyCsr";
     return ;
--select distinct * from "QBP_1"();
END;
$$ language plpgsql;

-----------------------------------------------------------------------


CREATE OR REPLACE FUNCTION "QBP_2"()
RETURNS TABLE("Id" integer,
                "DId"   integer,
                "User"  VARCHAR(64), 
                "Name"  VARCHAR(64) )
AS $$
declare
    "MyCsr" refcursor;
     "SqlStr" varchar(10240) := 'SELECT "Id", "DId", "User", "Name" from test ORDER BY "Name" ASC LIMIT 10 OFFSET 0';
BEGIN
    raise notice 'SQL :%', "SqlStr";
    return query execute "SqlStr";
--select distinct * from "QBP_2"();
END;
$$ language plpgsql;


---------------------------------------------------------------


CREATE OR REPLACE FUNCTION "QBP_3"()
RETURNS SETOF  "BPI"
AS $$
declare
    "Item"  "BPI";
     "SqlStr" varchar(10240) := 'SELECT "Id", "DId", "User", "Name" from test ORDER BY "Name" ASC LIMIT 10 OFFSET 0';
BEGIN
    raise notice 'SQL :%', "SqlStr";
    for "Item" in execute "SqlStr" LOOP
        return next "Item";
    end LOOP;
--select distinct * from "QBP_3"();
END;
$$ language plpgsql;

SQL1:select distinct * from "QBP_1"();

SQL2:select distinct * from "QBP_2"();

SQL3:select distinct * from "QBP_3"();

SQL4:SELECT distinct "Id", "DId", "User", "Name" from test ORDER BY "Name" ASC LIMIT 10 OFFSET 0;

returning:

postgres=# select distinct * from "QBP_1"();
NOTICE:  SQL :SELECT "Id", "DId", "User", "Name" from test ORDER BY "Name" ASC LIMIT 10 OFFSET 0
  Id  | DId |        User         |    Name
------+-----+---------------------+------------
  844 |   6 | 111                 | 111
 3242 |   6 | 201919-11:29:3:340  | sizhanerLD
  884 |   6 | 151                 | 151
  864 |   6 | 131                 | 131
  847 |   6 | 114                 | 114
  849 |   6 | 116                 | 116
 3241 |   6 | 201919-11:28:17:506 | sizhanerZB
 3239 |   6 | 201919-11:25:57:629 | sizhanerZB
 3240 |   6 | 201919-11:27:37:15  | sizhanerLD
 1655 |   6 | 1000000000          | 1000000000
(10 rows)

postgres=# select distinct * from "QBP_2"();
NOTICE:  SQL :SELECT "Id", "DId", "User", "Name" from test ORDER BY "Name" ASC LIMIT 10 OFFSET 0
  Id  | DId |        User         |    Name
------+-----+---------------------+------------
  844 |   6 | 111                 | 111
 3242 |   6 | 201919-11:29:3:340  | sizhanerLD
  884 |   6 | 151                 | 151
  864 |   6 | 131                 | 131
  847 |   6 | 114                 | 114
  849 |   6 | 116                 | 116
 3241 |   6 | 201919-11:28:17:506 | sizhanerZB
 3239 |   6 | 201919-11:25:57:629 | sizhanerZB
 3240 |   6 | 201919-11:27:37:15  | sizhanerLD
 1655 |   6 | 1000000000          | 1000000000
(10 rows)

postgres=# select distinct * from "QBP_3"();
NOTICE:  SQL :SELECT "Id", "DId", "User", "Name" from test ORDER BY "Name" ASC LIMIT 10 OFFSET 0
  Id  | DId |        User         |    Name
------+-----+---------------------+------------
  844 |   6 | 111                 | 111
 3242 |   6 | 201919-11:29:3:340  | sizhanerLD
  884 |   6 | 151                 | 151
  864 |   6 | 131                 | 131
  847 |   6 | 114                 | 114
  849 |   6 | 116                 | 116
 3241 |   6 | 201919-11:28:17:506 | sizhanerZB
 3239 |   6 | 201919-11:25:57:629 | sizhanerZB
 3240 |   6 | 201919-11:27:37:15  | sizhanerLD
 1655 |   6 | 1000000000          | 1000000000
(10 rows)

postgres=# SELECT distinct "Id", "DId", "User", "Name" from test ORDER BY "Name" ASC LIMIT 10 OFFSET 0;
  Id  | DId |        User         |    Name
------+-----+---------------------+------------
 1655 |   6 | 1000000000          | 1000000000
  844 |   6 | 111                 | 111
  847 |   6 | 114                 | 114
  849 |   6 | 116                 | 116
  864 |   6 | 131                 | 131
  884 |   6 | 151                 | 151
 3242 |   6 | 201919-11:29:3:340  | sizhanerLD
 3240 |   6 | 201919-11:27:37:15  | sizhanerLD
 3241 |   6 | 201919-11:28:17:506 | sizhanerZB
 3239 |   6 | 201919-11:25:57:629 | sizhanerZB
(10 rows)


如上代码所示。我为一个简单的测试创建了 3 个函数。但似乎 SQL 123 返回了错误的顺序。 (如果我删除“distinct”,则返回顺序正确)我是否错误地使用了“distinct”?为什么?

最后,我为我的 poooooooooooooooooooooor 英语道歉。希望不会影响你的阅读

【问题讨论】:

  • 与您的问题无关,但您使用游标和动态 SQL 完全是矫枉过正。您不需要 PL/pgSQL、循环或动态 SQL 来返回查询结果。
  • 你真的应该避免那些可怕的引用标识符。 wiki.postgresql.org/wiki/…

标签: sql postgresql distinct postgresql-11


【解决方案1】:

关系数据库中的表表示关系。关系是一种特殊类型的(多)集合。并且集合没有顺序。因此,除非 outermost 查询使用 ORDER BY 子句显式排序结果,否则 SQL 中的查询结果可以按任何顺序排列。

当然,在输出时,结果有某种物理顺序。但重要的一点是,当缺少ORDER BY 子句时,引擎可以按任何顺序返回结果。在您的情况下,引擎可能会以“好”的方式处理函数的中间结果,以便进行去重(DISTINCT),并且可以“重新排序”元组(甚至可能在每次发出查询时以另一个顺序)。

如果您想要一个有序的结果,请在最外层的查询中包含一个 ORDER BY 子句,如

SELECT DISTINCT
       *
       FROM "QBP_1"()
       ORDER BY "Name";

和其他功能的模拟。否则你不能期望一个特定的顺序,即也没有“错误的顺序”。

附带说明:请考虑不要使用这种总是需要引用的驼峰式标识符。这可能非常令人困惑。仅使用不带引号(小写)的标识符可以节省一些麻烦。

【讨论】:

  • 我误解了“distinct”。非常感谢您的回复。
  • 稍微扩展@sticky。 Postgres 对非双引号标识符不区分大小写。因此,如果您真的想在没有双引号的情况下使用 CamelCase,您可以。只要意识到,只要 Postgres 报告它,它就会被降低。因此,例如 Name 变为 name。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-21
  • 2013-02-28
  • 2021-08-24
  • 2017-01-04
  • 2016-01-26
  • 1970-01-01
相关资源
最近更新 更多