I have a simple MySQL query that I want to convert to PostgreSQL. After 3 days I finally quit as I don’t understand what wrong here:
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
I have tried to convert it but it says error on SET. Here is my query:
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
Can anyone please tell me what’s wrong with it? I can’t sleep just because of this.
------------------------------EDIT-------------------------------------
shares table
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 table
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 table
CREATE TABLE pool_worker (
id integer NOT NULL,
"associatedUserId" integer NOT NULL,
username character(50),
password character(255),
allowed_hosts text
);
First, I formatted to arrive at this less confusing but still incorrect query:
There are multiple distinct errors and more sub-optimal parts in this statement. Errors come first and with bold emphasis. The last few items are just recommendations.
Missing alias
ufor webuser. A trivial mistake.Missing join between
wanda. Results in a cross join, which hardly makes any sense and is a very expensive mistake as far as performance is concerned. It is also completely uncalled for, you can drop the redundant second instance ofwebuserfrom the query.SET (shares_this_round) = (a.id)is a syntax error. You cannot wrap a column name in theSETclause in parenthesis. It would be pointless anyway, just like the parenthesis arounda.id. The latter isn’t a syntax error, though.As it turns out after comments and question update, you created the table with double-quoted
"CamelCase"identifiers (which I advise not to use, ever, for exactly the kind of problems we just ran into). Read the chapter Identifiers and Key Words in the manual to understand what went wrong. In short: non-standard identifiers (with upper-case letters or reserved words, ..) have to be double-quoted at all times.I amended the query below to fit the new information.
The aggregate function
count()never returnsNULLby definition.COALESCEis pointless in this context. I quote the manual on aggregate functions:Emphasis mine. The count itself works, because
NULLvalues are not counted, so you actually get 0 where nos.idis found.I also use a different column alias (
id_ct), becauseidfor the count is just misleading.WHERE s.our_result = 'Y'… ifour_resultis of typeboolean, like it seems it should be, you can simplify to justWHERE s.our_result. I am guessing here, because you did not provide the necessary table definition.It is almost always a good idea to avoid UPDATEs that do not actually change anything (rare exceptions apply). I added a second
WHEREclause to eliminate those:If
shares_this_roundis definedNOT NULL, you can use<>instead becauseid_ctcannot beNULL. (Again, missing info in question.)USING(username)is just a notational shortcut that can be used here.Put everything together to arrive at this correct form: