微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

PostgreSQL UPDATE相当于MySQL查询

我有一个简单的MySQL查询,我想转换为Postgresql. 3天后我终于退出了,因为我不明白这里有什么不妥:

UPDATE webUsers u, 
(SELECT IFNULL(count(s.id),0) AS id, p.associatedUserId FROM pool_worker p 
LEFT JOIN shares s ON p.username=s.username 
WHERE s.our_result='Y' GROUP BY p.associatedUserId) a
SET shares_this_round = a.id WHERE u.id = a.associatedUserId

我试图转换它,但它说SET上的错误.这是我的查询

UPDATE webusers 
SET (shares_this_round) = (a.id)
FROM (SELECT coalesce(count(s.id),0) AS id, p.associatedUserId FROM pool_worker p 
LEFT JOIN shares s ON p.username=s.username WHERE s.our_result='Y' GROUP BY p.associatedUserId) a, webusers w WHERE u.id = a.associatedUserId

谁能告诉我它有什么问题?因为这个原因,我无法入睡.

     ------------------------------EDIT-------------------------------------

股份表

CREATE TABLE shares (
id bigint NOT NULL,
rem_host character varying(255) NOT NULL,
username character varying(120) NOT NULL,
our_result character(255) NOT NULL,
upstream_result character(255),
reason character varying(50),
solution character varying(1000) NOT NULL,
"time" timestamp without time zone DEFAULT Now() NOT NULL
);

webusers表

CREATE TABLE webusers (
id integer NOT NULL,
admin integer NOT NULL,
username character varying(40) NOT NULL,
pass character varying(255) NOT NULL,
email character varying(255) NOT NULL,
"emailAuthPin" character varying(10) NOT NULL,
secret character varying(10) NOT NULL,
"loggedIp" character varying(255) NOT NULL,
"sessionTimeoutStamp" integer NOT NULL,
"accountLocked" integer NOT NULL,
"accountFailedAttempts" integer NOT NULL,
pin character varying(255) NOT NULL,
share_count integer DEFAULT 0 NOT NULL,
stale_share_count integer DEFAULT 0 NOT NULL,
shares_this_round integer DEFAULT 0 NOT NULL,
api_key character varying(255),
"activeEmail" integer,
donate_percent character varying(11) DEFAULT '1'::character varying,
btc_lock character(255) DEFAULT '0'::bpchar NOT NULL
);

pool_workes表

CREATE TABLE pool_worker (
id integer NOT NULL,
"associatedUserId" integer NOT NULL,
username character(50),
password character(255),
allowed_hosts text
);

解决方法:

首先,我格式化以达到这个不那么令人困惑但仍然不正确的查询

UPDATE webusers 
SET   (shares_this_round) = (a.id)
FROM  (
   SELECT coalesce(count(s.id),0) AS id, p.associatedUserId
   FROM   pool_worker p 
   LEFT   JOIN shares s ON p.username=s.username
   WHERE  s.our_result='Y'
   GROUP  BY p.associatedUserId) a
   , webusers w
WHERE u.id = a.associatedUserId

此语句中有多个不同的错误和更多次优部分.错误首先出现并大胆强调.最后几项只是建议.

>缺少webuser的别名u.一个微不足道的错误.
>缺少w和a之间的连接.结果是交叉连接,这几乎没有任何意义,就性能而言是一个非常昂贵的错误.它也完全不需要,您可以从查询删除冗余的webuser第二个实例.
> SET(shares_this_round)=(a.id)是语法错误.您不能在括号中的SET子句中包装列名.无论如何,这都是毫无意义的,就像a.id周围的括号一样.但后者不是语法错误.
>事实证明,在评论和问题更新之后,您使用双引号“CamelCase”标识符创建了表格(我建议不要使用它,因为我们刚遇到的问题就是这样).阅读手册中的第Identifiers and Key Words章,了解出了什么问题.简而言之:非标准标识符(带大写字母或保留字,……)必须始终双引号.
修改了下面的查询以适应新信息.
>根据定义,聚合函数count()永远不会返回NULL.在这种背景下,COALESCE毫无意义.我引用the manual on aggregate functions

It should be noted that except for count, these functions return a
null value when no rows are selected.

强调我的.计数本身有效,因为不计算NULL值,所以实际上在没有找到s.id的情况下得到0.
>我还使用了不同的列别名(id_ct),因为计数的id只是误导.
> WHERE s.our_result =’Y’…如果our_result的类型为boolean,就像它应该是的那样,你可以简化为WHERE s.our_result.我在这里猜测,因为你没有提供必要的表定义.
>避免实际上没有改变任何内容的UPDATE几乎总是一个好主意(很少有例外情况适用).我添加了第二个WHERE子句来消除这些:

AND   w.shares_this_round IS disTINCT FROM a.id

如果shares_this_round定义为NOT NULL,则可以使用<>相反,因为id_ct不能为NULL. (再次,缺少有问题的信息.)
> USING(用户名)只是一个可以在这里使用的符号快捷方式.

将所有内容放在一起以达到这种正确的形式:

UPDATE webusers w
SET    shares_this_round = a.id_ct
FROM  (
   SELECT p."associatedUserId", count(s.id) AS id_ct
   FROM   pool_worker p 
   LEFT   JOIN shares s USING (username)
   WHERE  s.our_result = 'Y'                        -- boolean?
   GROUP  BY p."associatedUserId"
   ) a
WHERE w.id = a."associatedUserId"
AND   w.shares_this_round IS disTINCT FROM a.id_ct  -- avoid empty updates

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐