3

PostgreSQL に変換したい単純な MySQL クエリがあります。ここで何が悪いのか理解できないので、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
);
4

1 に答える 1

5

最初に、次のようなややこしいが、まだ正しくないクエリにたどり着くように書式を設定しました。

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

このステートメントには、複数の明確なエラーと最適ではない部分があります。エラーが最初に来て、 大胆に強調されます。最後のいくつかの項目は単なる推奨事項です。

  1. Web ユーザーのエイリアス uがありません。些細な間違い。

  2. との間の結合wがありませんa。結果としてクロス結合が発生しますが、これはほとんど意味がなく、パフォーマンスに関する限り非常にコストのかかる間違いです。また、完全に不要です。クエリから冗長な 2 番目のインスタンスを削除できます。webuser

  3. SET (shares_this_round) = (a.id)構文エラーです。SET括弧内の句で列名をラップすることはできません。の周りのかっこのように、とにかく無意味ですa.id。ただし、後者は構文エラーではありません。

  4. コメントと質問の更新後に判明したように、二重引用符で囲まれた"CamelCase"識別子を使用してテーブルを作成しました(これは、まさに私たちが遭遇した種類の問題のために、決して使用しないことをお勧めします)。マニュアルの「識別子とキーワード」の章を読んで、何が問題なのかを理解してください。つまり、非標準の識別子 (大文字または予約語など) は、常に二重引用符で囲む必要があります。
    新しい情報に合わせて以下のクエリを修正しました。

  5. 定義上、集計関数count()は戻りません。この文脈では無意味です。集計関数に関するマニュアルを引用します。NULLCOALESCE

    count を除いて、行が選択されていない場合、これらの関数は null 値を返すことに注意してください。

    鉱山を強調します。値がカウントされないため、カウント自体が機能するためNULL、実際には値が見つからない場合は 0 になりますs.id

  6. カウントが誤解を招くだけなので、別の列エイリアス ( id_ct)も使用します。id

  7. WHERE s.our_result = 'Y'...our_resultがタイプの場合boolean、あるべきように見えるので、単に に単純化できますWHERE s.our_result。必要なテーブル定義を提供しなかったため、ここで推測しています。

  8. ほとんどの場合、実際には何も変更しない UPDATE を避けることをお勧めします (まれな例外が適用されます)。WHEREそれらを排除するために2番目の句を追加しました。

    AND   w.shares_this_round IS DISTINCT FROM a.id
    

    shares_this_roundが定義されている場合は、 を使用できないため、代わりにNOT NULL使用できます。(繰り返しますが、問題の情報が欠落しています。)<>id_ctNULL

  9. USING(username)ここで使用できる単なる表記上のショートカットです。

すべてを組み合わせて、この正しいフォームに到達します。

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
于 2012-11-10T03:58:47.377 に答える