X-Original-To: pgsql-sql-postgresql.org@localhost.postgresql.org Received: from localhost (unknown [200.46.204.144]) by svr1.postgresql.org (Postfix) with ESMTP id 745D13A2B97 for ; Sat, 15 Jan 2005 08:25:31 +0000 (GMT) Received: from svr1.postgresql.org ([200.46.204.71]) by localhost (av.hub.org [200.46.204.144]) (amavisd-new, port 10024) with ESMTP id 89755-03 for ; Sat, 15 Jan 2005 08:25:20 +0000 (GMT) Received: from boutiquenumerique.com (boutiquenumerique.com [82.67.9.10]) by svr1.postgresql.org (Postfix) with ESMTP id 963B13A2BD6 for ; Sat, 15 Jan 2005 08:25:20 +0000 (GMT) Received: (qmail 1816 invoked from network); 15 Jan 2005 09:25:29 +0100 Received: from unknown (HELO musicbox) (boutiquenumerique-lists@192.168.0.2) by boutiquenumerique.com with SMTP; 15 Jan 2005 09:25:29 +0100 Date: Sat, 15 Jan 2005 09:26:22 +0100 To: "Michael Ossareh" , "'pgsql-sql@postgresql.org'" Subject: Re: SQL Query Performance tips References: <5CCF98464386D4119F1200306E0050CC01447BE6@betauk.london.12snap.com> From: PFC Organization: =?iso-8859-15?Q?La_Boutique_Num=E9rique?= Content-Type: text/plain; format=flowed; delsp=yes; charset=iso-8859-15 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID: In-Reply-To: <5CCF98464386D4119F1200306E0050CC01447BE6@betauk.london.12snap.com> User-Agent: Opera M2/7.54 (Linux, build 751) X-Virus-Scanned: by amavisd-new at hub.org X-Spam-Status: No, hits=0.002 tagged_above=0 required=5 tests=AWL X-Spam-Level: X-Archive-Number: 200501/108 X-Sequence-Number: 19896 If I understand well a person has all the free weapons which have a level <= to his own level, and of course all the weapons he bought. 1) get da weapons One query can only use one index. Bad for you ! Let's split the free and non-free weapons. 1a) free weapons SELECT weapon_alignment, count(1) as cnt FROM weapons WHERE weapon_level < (user_level) AND weapon_cost = 0 GROUP BY weapon_alignment; No need for distinct anymore ! Note also that distinct'ing on weapon_name is a slower than on weapon_id. You can create an index on (weapon_cost,weapon_level) but I don't think it'll be useful. For ultimate speed, as this does not depend on the user_id, only the level, you can store the results of this in a table, precalculating the results for all levels (if there are like 10 levels, it'll be a big win). 1b) weapons bought by the user SELECT w.weapon_alignment, count(1) as cnt FROM weapons w, user_weapons uw WHERE w.weapon_id = uw.weapon_id AND uw.user_id = (the user_id) AND w.weapon_cost > 0 GROUP BY weapon_alignment; You'll note that the weapons in 1a) had cose=0 so they cannot appear here, no need to distinct the two. 2) combine the two SELECT weapon_alignment, sum(cnt) FROM (SELECT weapon_alignment, count(1) as cnt FROM weapons WHERE weapon_level < (user_level) AND weapon_cost = 0 GROUP BY weapon_alignment) UNION ALL SELECT w.weapon_alignment, count(1) as cnt FROM weapons w, user_weapons uw WHERE w.weapon_id = uw.weapon_id AND uw.user_id = (the user_id) AND w.weapon_cost > 0 GROUP BY weapon_alignment) GROUP BY weapon_alignment; You can also do this : SELECT weapon_alignment, count(1) as cnt FROM (SELECT weapon_alignment FROM weapons WHERE weapon_level < (user_level) AND weapon_cost = 0) UNION ALL SELECT w.weapon_alignment FROM weapons w, user_weapons uw WHERE w.weapon_id = uw.weapon_id AND uw.user_id = (the user_id) AND w.weapon_cost > 0) GROUP BY weapon_alignment; How does it turn out ?