0

UPDATEコマンドのクエリからcartProduct派生テーブルを参照する必要があります。誰かが私に何を間違っているのか、どうすれば修正できるのか説明してもらえますか?

UPDATE memberships SET points = (points + COALESCE( 
    (SELECT pts 
    FROM (
        SELECT pid0, SUM (S) as Pts
        FROM ( 
            (SELECT pid0, SUM (pts1) as S
            FROM 
                (SELECT DISTINCT pid0, pid0,pts1
                FROM cartProduct
                WHERE pid0 = i1) as pointsForPath 
            GROUP BY pid0)) as allPtsTbl
        GROUP BY pid0) as temp 
    WHERE memberships.cid = 57010 AND memberships.pid = temp.pid0 ),
0))
FROM (
    SELECT t0.pid as pid0,t1.pid as pid1,t1.invitedby as i1,t1.points as pts1, t2.pid as pid2,t2.invitedby as i2,t2.points as pts2,t3.pid as pid3,t3.invitedby as i3, t3.points as pts3
    FROM memberships t0, memberships  t1, memberships  t2, memberships  t3
    WHERE t0.cid = t1.cid AND t1.cid = t2.cid AND t2.cid = t3.cid) as cartProduct;

このクエリが何をしなければならないかは、私が最適化したい複雑なクエリの小さな断片を引き起こすので、実際には問題ではありません。私の唯一の質問は、UPDATEサブクエリからcartProductを参照する方法です。最適化したいクエリはCコードで生成されます...ご覧のとおり、同じことを何度も計算する必要があります。このクエリには3つの派生テーブルしかありませんが、100以上になる可能性があるため、計算するには10時間以上待つ必要があります。

UPDATE memberships SET points = points + COALESCE((
SELECT pts 
FROM (
    SELECT pid0, SUM (S) as Pts
    FROM ( 
        SELECT pid0, SUM (pts1) as S
        FROM 
            (SELECT DISTINCT pid0, pid1,pts1
            FROM (
                SELECT t0.pid as pid0, t1.pid as pid1, t1.invitedby as i1, t1.points as pts1 
                FROM memberships t0, memberships t1
                WHERE t0.cid = 57010 AND t1.cid = 57010) as paths
            WHERE pid0 = i1) as pointsForPath
        GROUP BY pid0
        UNION ALL
        SELECT pid0, SUM (pts2) as S
        FROM (
            SELECT DISTINCT pid0, pid2,pts2
            FROM (
                SELECT t0.pid as pid0, t1.pid as pid1, t1.invitedby as i1, t1.points as pts1 , t2.pid as pid2, t2.invitedby as i2, t2.points as pts2 
                FROM memberships t0, memberships t1, memberships t2
                WHERE t0.cid = 57010 AND t1.cid = 57010 AND t2.cid = 57010) as paths
            WHERE pid0 = i1 AND pid1 = i2) as pointsForPath
        GROUP BY pid0
        UNION ALL
        SELECT pid0, SUM (pts3) as S
        FROM (
            SELECT DISTINCT pid0, pid3,pts3
            FROM (
                SELECT t0.pid as pid0, t1.pid as pid1, t1.invitedby as i1, t1.points as pts1 , t2.pid as pid2, t2.invitedby as i2, t2.points as pts2 , t3.pid as pid3, t3.invitedby as i3, t3.points as pts3 
                FROM memberships t0, memberships t1, memberships t2, memberships t3
                WHERE t0.cid = 57010 AND t1.cid = 57010 AND t2.cid = 57010 AND t3.cid = 57010) as paths
            WHERE pid0 = i1 AND pid1 = i2 AND pid2 = i3) as pointsForPath
        GROUP BY pid0 ) as allPtsTbl
GROUP BY pid0) as temp WHERE memberships.cid = 57010 AND memberships.pid = temp.pid0 ),0)

英語が下手でごめんなさい。どうもありがとう。

4

1 に答える 1

0

パフォーマンスが問題になる場合は、次のことを試してください。

update memberships
    set points = points + coalesce(s.points, 0)
    from (nasty union all'ed subquery) s
    where memberships.id = s.id

(これは、pid0フィールドの名前をidに変更することを前提としています。)

そうは言っても、次のことを考慮する必要があります。

  1. 適切な結合構文を学びます。英語で「hath」や「thee」を使用するように、「where」句で結合を行うことは古語になりつつあります。各テーブルからフェッチされているレコードの数がわからないため、特定の値(実行していること)を選択して暗黙的に結合を行うことは非常に危険です。クエリを少し変更すると、悪影響が生じる可能性があります(2人のユーザーを選択するなど)。 1つではなく)。
  2. 厄介なサブクエリを一時テーブルに配置します。通常、一時テーブルは推奨しませんが、オプティマイザーが混乱する場合があります(これは、選択、削除、更新が混在するクエリで特に可能です)。
  3. なぜあなたはgroupbyの前に明確なことをしているのですか。まず、「sum(distinct)」を実行できますが、これはほとんど必要ありません。これは、結合に問題があることを示しています。また、結合が正しくないと、クエリが完了しません。
于 2012-05-27T14:03:10.313 に答える