Re: [SQL] cross tables, SELECT expressions, and GROUP BY problem

2006-04-02 Thread Ross Johnson
On Sun, 2006-04-02 at 16:43 +1000, Ross Johnson wrote:
> Hi,
> 
> I'm relatively stretched when it comes to SQL but I'm getting there. I
> have a question though:
> 
> Thanks to various web sites I've succeeded in creating simple cross
> tables in PostgreSQL. I'm now trying more complicated examples
> (migrating queries from MS Access to PostgreSQL). I'm stuck on getting
> grouping to work where the selection element isn't a real table field,
> where it is generated by a CASE statement. Here's a full actual SELECT
> statement, that works but isn't quite what I need, followed by the first
> few rows of output:
> 
> SELECT DISTINCT
>   CASE
>   WHEN lower(c."Order") = 'coleoptera' THEN 5
>   WHEN lower(c."Order") = 'trichoptera' THEN 8
>   WHEN lower(c."Order") = 'ephemeroptera' THEN 6
>   WHEN lower(c."Order") = 'plecoptera' THEN 7
>   WHEN lower(c."Class") = 'oligochaeta' THEN 1
>   WHEN lower(c."Family") LIKE 'chiron%' THEN 2
>   WHEN lower(c."Order") = 'diptera' AND lower(c."Family") NOT 
> LIKE 'chiron%' THEN 3
>   ELSE 4
>   END AS "Ranking",
>   CASE
>   WHEN lower(c."Order") = 'coleoptera' THEN 'Coleoptera'
>   WHEN lower(c."Order") = 'trichoptera' THEN 'Trichoptera'
>   WHEN lower(c."Order") = 'ephemeroptera' THEN 'Ephemeroptera'
>   WHEN lower(c."Order") = 'plecoptera' THEN 'Plecoptera'
>   WHEN lower(c."Class") = 'oligochaeta' THEN 'Oligochaeta'
>   WHEN lower(c."Family") LIKE 'chiron%' THEN 'Chironomidae'
>   WHEN lower(c."Order") = 'diptera' AND lower(c."Family") NOT 
> LIKE 'chiron%' THEN 'Diptera (Other)'
>   ELSE 'Other'
>   END AS "Taxa",
>   SUM(CASE WHEN b."LocationCode" = '011' THEN c."Count" END) AS 
> "011",
>   SUM(CASE WHEN b."LocationCode" = '012' THEN c."Count" END) AS 
> "012",
>   SUM(CASE WHEN b."LocationCode" = '013' THEN c."Count" END) AS 
> "013",
>   SUM(CASE WHEN b."LocationCode" = '014' THEN c."Count" END) AS 
> "014"
> FROM "tblBugIDSheetInfo" b
>   INNER JOIN "tblBugCount" c USING ("BugSheetID")
> GROUP BY c."Order", c."Class", c."Family"
> ORDER BY "Ranking"
> 
> Generates the following output:
> 
> Ranking   Taxa011 012 013 014
> ---
> 1 "Oligochaeta"   487 171117591078
> 1 "Oligochaeta"   7   
> 1 "Oligochaeta"   
> 2 "Chironomidae"  1385233515001513
> 2 "Chironomidae"  
> 3 "Diptera (Other)"   5
> 3 "Diptera (Other)"   1   1   3
> 3 "Diptera (Other)"   199 19  40  37
> 3 "Diptera (Other)"   
> ...

I should add that I've just tried the following query, which is just a
rearrangement of the above query using a sub-SELECT, and the result is
the same as above apart from a slightly different ordering of the rows.
That is, GROUP BY "Ranking" still doesn't appear to do anything. I was
under the impression that a sub-SELECT creates a temporary, or at least
a pseudo-temporary table (a "virtual" table as it's called in the
documentation), so I would have expected this query to work even if the
above one doesn't.


SELECT DISTINCT
"Ranking", "Taxa",
SUM(CASE WHEN b."LocationCode" = '011' THEN c."Count" END) AS 
"011",
SUM(CASE WHEN b."LocationCode" = '012' THEN c."Count" END) AS 
"012",
SUM(CASE WHEN b."LocationCode" = '013' THEN c."Count" END) AS 
"013",
SUM(CASE WHEN b."LocationCode" = '014' THEN c."Count" END) AS 
"014"
FROM "tblBugIDSheetInfo" b
INNER JOIN (
SELECT "BugSheetID",
CASE
WHEN lower("Order") = 'coleoptera' THEN 5
WHEN lower("Order") = 'trichoptera' THEN 8
WHEN lower("Order") = 'ephemeroptera' THEN 6
WHEN lower("Order") = 'plecoptera' THEN 7
WHEN lower("Class") = 'oligochaeta' THEN 1
WHEN lower("Family") LIKE 'chiron%' THEN 2
WHEN lower("Order") = 'diptera' AND lower("Family") NOT 
LIKE 'chiron%' THEN 3
ELSE 4
END AS "Ranking",
CASE
WHEN lower("Order") = 'coleoptera' THEN 'Coleoptera'
WHEN lower("Order") = 'trichoptera' THEN 'Trichoptera'
WHEN lower("Order") = 'ephemeroptera' THEN 
'Ephemeroptera'
WHEN lower("Order") = 'plecoptera' THEN 'Plecoptera'
WHEN lower("Class") = 'oligochaeta' THEN 'Oligochaeta'
 

Re: [SQL] cross tables, SELECT expressions, and GROUP BY problem

2006-04-02 Thread Ross Johnson
Following up my own question again, I've realised my error and solved my
problem - in the interests of completing this thread, the working query
(two versions) can be found below...

On Sun, 2006-04-02 at 18:00 +1000, Ross Johnson wrote:
> On Sun, 2006-04-02 at 16:43 +1000, Ross Johnson wrote:
> > Hi,
> > 
> > I'm relatively stretched when it comes to SQL but I'm getting there. I
> > have a question though:
> > 
> > Thanks to various web sites I've succeeded in creating simple cross
> > tables in PostgreSQL. I'm now trying more complicated examples
> > (migrating queries from MS Access to PostgreSQL). I'm stuck on getting
> > grouping to work where the selection element isn't a real table field,
> > where it is generated by a CASE statement. Here's a full actual SELECT
> > statement, that works but isn't quite what I need, followed by the first
> > few rows of output:
> > 
> > SELECT DISTINCT
> > CASE
> > WHEN lower(c."Order") = 'coleoptera' THEN 5
> > WHEN lower(c."Order") = 'trichoptera' THEN 8
> > WHEN lower(c."Order") = 'ephemeroptera' THEN 6
> > WHEN lower(c."Order") = 'plecoptera' THEN 7
> > WHEN lower(c."Class") = 'oligochaeta' THEN 1
> > WHEN lower(c."Family") LIKE 'chiron%' THEN 2
> > WHEN lower(c."Order") = 'diptera' AND lower(c."Family") NOT 
> > LIKE 'chiron%' THEN 3
> > ELSE 4
> > END AS "Ranking",
> > CASE
> > WHEN lower(c."Order") = 'coleoptera' THEN 'Coleoptera'
> > WHEN lower(c."Order") = 'trichoptera' THEN 'Trichoptera'
> > WHEN lower(c."Order") = 'ephemeroptera' THEN 'Ephemeroptera'
> > WHEN lower(c."Order") = 'plecoptera' THEN 'Plecoptera'
> > WHEN lower(c."Class") = 'oligochaeta' THEN 'Oligochaeta'
> > WHEN lower(c."Family") LIKE 'chiron%' THEN 'Chironomidae'
> > WHEN lower(c."Order") = 'diptera' AND lower(c."Family") NOT 
> > LIKE 'chiron%' THEN 'Diptera (Other)'
> > ELSE 'Other'
> > END AS "Taxa",
> > SUM(CASE WHEN b."LocationCode" = '011' THEN c."Count" END) AS 
> > "011",
> > SUM(CASE WHEN b."LocationCode" = '012' THEN c."Count" END) AS 
> > "012",
> > SUM(CASE WHEN b."LocationCode" = '013' THEN c."Count" END) AS 
> > "013",
> > SUM(CASE WHEN b."LocationCode" = '014' THEN c."Count" END) AS 
> > "014"
> > FROM "tblBugIDSheetInfo" b
> > INNER JOIN "tblBugCount" c USING ("BugSheetID")
> > GROUP BY c."Order", c."Class", c."Family"
> > ORDER BY "Ranking"
> > 
> > Generates the following output:
> > 
> > Ranking Taxa011 012 013 014
> > ---
> > 1   "Oligochaeta"   487 171117591078
> > 1   "Oligochaeta"   7   
> > 1   "Oligochaeta"   
> > 2   "Chironomidae"  1385233515001513
> > 2   "Chironomidae"  
> > 3   "Diptera (Other)"   5
> > 3   "Diptera (Other)"   1   1   3
> > 3   "Diptera (Other)"   199 19  40  37
> > 3   "Diptera (Other)"   
> > ...
> 
> I should add that I've just tried the following query, which is just a
> rearrangement of the above query using a sub-SELECT, and the result is
> the same as above apart from a slightly different ordering of the rows.
> That is, GROUP BY "Ranking" still doesn't appear to do anything. I was
> under the impression that a sub-SELECT creates a temporary, or at least
> a pseudo-temporary table (a "virtual" table as it's called in the
> documentation), so I would have expected this query to work even if the
> above one doesn't.
> 
> 
> SELECT DISTINCT
>   "Ranking", "Taxa",
>   SUM(CASE WHEN b."LocationCode" = '011' THEN c."Count" END) AS 
> "011",
>   SUM(CASE WHEN b."LocationCode" = '012' THEN c."Count" END) AS 
> "012",
>   SUM(CASE WHEN b."LocationCode" = '013' THEN c."Count" END) AS 
> "013",
>   SUM(CASE WHEN b."LocationCode" = '014' THEN c."Count" END) AS 
> "014"
> FROM "tblBugIDSheetInfo" b
>   INNER JOIN (
>   SELECT "BugSheetID",
>   CASE
>   WHEN lower("Order") = 'coleoptera' THEN 5
>   WHEN lower("Order") = 'trichoptera' THEN 8
>   WHEN lower("Order") = 'ephemeroptera' THEN 6
>   WHEN lower("Order") = 'plecoptera' THEN 7
>   WHEN lower("Class") = 'oligochaeta' THEN 1
>   WHEN lower("Family") LIKE 'chiron%' THEN 2
>   WHEN lower("Order") = 'diptera' AND lower("Family") NOT 
> LIKE 'chiron%' THEN 3
>   ELSE 4
>   END AS "Ranking",
>   CASE
>   WHEN lower("Order") = 'coleoptera' THEN 'Cole

[SQL] References NULL field

2006-04-02 Thread Paul M Foster

This is PostgreSQL 7.4 (long story). I have a table, registrars, which
has, among other things,

note_id integer references notes

The notes table has, among other things,

note_id integer default nextval('notes_seq')

Right now, there's nothing in the notes table, and all the records in
the registrars table have null for their note_id field.

I want to do a query (in PHP, FWIW) that returns all the fields in
registrars, and the contents of any relevant notes records, or null for
those fields if there is no corresponding record in the notes table. But
when I do

SELECT * FROM registrars, notes WHERE regname = 'blah'

no matter that I put after the 'blah' (or nothing), I get no results. As
soon as I add notes into the tables being queried, I get nothing.

There's some special way I need to shape this query, but I don't know
what it is. Any help would be appreciated.

--
Paul M. Foster



---(end of broadcast)---
TIP 9: In versions below 8.0, the planner will ignore your desire to
  choose an index scan if your joining column's datatypes do not
  match


Re: [SQL] References NULL field

2006-04-02 Thread Michael Fuhr
On Sun, Apr 02, 2006 at 11:43:34PM -0400, Paul M Foster wrote:
> I want to do a query (in PHP, FWIW) that returns all the fields in
> registrars, and the contents of any relevant notes records, or null for
> those fields if there is no corresponding record in the notes table. But
> when I do
> 
> SELECT * FROM registrars, notes WHERE regname = 'blah'
> 
> no matter that I put after the 'blah' (or nothing), I get no results. As
> soon as I add notes into the tables being queried, I get nothing.

The above query does a cross (cartesian) join of registrars and
notes.  Since notes is empty the join result is empty.  Try an
outer join:

SELECT *
FROM registrars LEFT OUTER JOIN notes USING (note_id)
WHERE regname = 'blah';

-- 
Michael Fuhr

---(end of broadcast)---
TIP 1: if posting/reading through Usenet, please send an appropriate
   subscribe-nomail command to [EMAIL PROTECTED] so that your
   message can get through to the mailing list cleanly