anjanb
anjanb

Reputation: 13867

Postgres SQL : how to do GROUP BY in this SQL

We have the below SQL that generates a report from the Audit Tables family_audit and family_address_audit.

(SELECT fam.familyserialno, fam.familyname, addr.housenumber, addr.address1,
        COALESCE(fam.operation, addr.operation) op,
        COALESCE(fam.username, addr.username) usr,
        COALESCE(fam.adddate, addr.adddate) add_date,
        (SELECT r.userrolename 
           FROM userrole_master r, user_master u 
          WHERE u.loginid=COALESCE(fam.username, addr.username) AND r.userrole_id=u.userrole_id) rolename
  FROM family_audit fam
       INNER JOIN family_address_audit addr USING(txid, family_id)
WHERE (fam.node_id = 8) AND (fam.familyserialno >=1 and fam.familyserialno <=5)
)
UNION
(SELECT fam.familyserialno, fam.familyname,
        addr.housenumber, addr.address1,
        COALESCE(fam.operation, addr.operation) op,
        COALESCE(fam.username, addr.username) usr,
        COALESCE(fam.adddate, addr.adddate) add_date,
        (SELECT r.userrolename 
           FROM userrole_master r, user_master u 
          WHERE u.loginid=COALESCE(fam.username, addr.username) AND r.userrole_id=u.userrole_id) rolename
   FROM family_audit fam
        FULL OUTER JOIN family_address_audit addr USING(txid, family_id)
  WHERE ((fam.familyserialno IS NULL and addr.family_id in 
             (select family_id 
                from family 
               where familyserialno >=1 and familyserialno <=5 and node_id =8)) 
         OR ((addr.family_id IS NULL) and ((fam.familyserialno >=1 and fam.familyserialno <=5) and fam.node_id=8) ) )
)
ORDER BY add_date DESC;

A typical output from the "above" SQL is as below

 familyserialno | familyname | housenumber |  address1  | op |  usr  |        add_date         | rolename
----------------+------------+-------------+------------+----+-------+-------------------------+----------
              3 | thirda     |             |            | U  | admin | 2010-11-24 15:29:34.312 | admin
                |            | 34324       | sdfdsfdsf  | U  | admin | 2010-11-24 15:28:42.314 | admin
              3 | third      |             |            | I  | admin | 2010-11-24 15:28:34.576 | admin
                |            | 333         | sdfdsf     | U  | admin | 2010-11-24 15:18:57.129 | admin
              2 | aSecond    |             |            | I  | admin | 2010-11-24 14:58:15.477 | admin
              1 | anjanFirst | anjanFirst  | anjanFirst | I  | admin | 2010-11-24 14:12:35.477 | admin

======================

I want to group the output by fam.familyserialno. So, I modified the above SQL as below; However, that results in an error (at the end)

SELECT * from 
((SELECT fam.familyserialno, fam.familyname, addr.housenumber, addr.address1,
        COALESCE(fam.operation, addr.operation) op,
        COALESCE(fam.username, addr.username) usr,
        COALESCE(fam.adddate, addr.adddate) add_date,
        (SELECT r.userrolename 
           FROM userrole_master r, user_master u 
          WHERE u.loginid=COALESCE(fam.username, addr.username) AND r.userrole_id=u.userrole_id) rolename
  FROM family_audit fam
       INNER JOIN family_address_audit addr USING(txid, family_id)
WHERE (fam.node_id = 8) AND (fam.familyserialno >=1 and fam.familyserialno <=5)
)
UNION
(SELECT fam.familyserialno, fam.familyname,
        addr.housenumber, addr.address1,
        COALESCE(fam.operation, addr.operation) op,
        COALESCE(fam.username, addr.username) usr,
        COALESCE(fam.adddate, addr.adddate) add_date,
        (SELECT r.userrolename 
           FROM userrole_master r, user_master u 
          WHERE u.loginid=COALESCE(fam.username, addr.username) AND r.userrole_id=u.userrole_id) rolename
   FROM family_audit fam
        FULL OUTER JOIN family_address_audit addr USING(txid, family_id)
  WHERE ((fam.familyserialno IS NULL and addr.family_id in 
             (select family_id 
                from family 
               where familyserialno >=1 and familyserialno <=5 and node_id =8)) 
         OR ((addr.family_id IS NULL) and ((fam.familyserialno >=1 and fam.familyserialno <=5) and fam.node_id=8) ) )
))
GROUP BY 1 
ORDER BY 7 DESC;

ERROR: subquery in FROM must have an alias LINE 2: ((SELECT fam.familyserialno, fam.familyname, addr.housenumbe... ^ HINT: For example, FROM (SELECT ...) [AS] foo.

How do I fix this ? We really need all the rows to be grouped by fam.familyserialno.

Thank you very much,

P.S : We are using Postgres 8.4.4.

Upvotes: 1

Views: 11040

Answers (1)

jmz
jmz

Reputation: 5479

You need to alias the subquery, as in:

 SELECT * FROM ((SELECT ...) UNION (SELECT ...)) AS foo GROUP BY 1 ORDER BY 7 DESC;

Here foo is an alias for the subquery.

Upvotes: 10

Related Questions