Jochem van Dieten <[EMAIL PROTECTED]> wrote on 06/22/2005 07:34:30 AM:
> On 6/22/05, David Kagiri wrote: > > When i run the queries below they all work just fine > > > > SELECT sum(consultation)+ sum(laboratory) FROM nairobi, > familymembers WHERE familymembers.dependantid = nairobi.memberid and > familymembers.memberid = "AKI00001" > > > > SELECT sum(consultation)+ sum(laboratory) FROM riftvalley, > familymembers WHERE familymembers.dependantid = riftvalley.memberid > and familymembers.memberid = "AKI00001" > > > > SELECT sum(consultation)+ sum(laboratory) FROM coast,familymembers > WHERE familymembers.dependantid = coast.memberid and familymembers. > memberid = "AKI00001" > > > > But i would like to run the querys above as one query that will > return a value that will be equivalent to the sum of the values of > those queries. i hope its possible. is it? i am using MySQL version 4.1.7 > SELECT sum(consultation)+ sum(laboratory) > FROM familymembers fm > INNER JOIN coast ON fm.dependantid = coast.memberid > INNER JOIN riftvalley ON fm.dependantid = riftvalley.memberid > INNER JOIN nairobi ON fm.dependantid = nairobi.memberid > WHERE fm.memberid = "AKI00001" > Jochem I hate to be the bearer of bad news but unless there is a very special arrangement of the data in these tables, that query is doomed to failure. It will fail because of HOW joined tables are actually joined. I will try to be brief (you will need to un-wrap some of this to help it make sense) Here is some sample data and an example why this query probably won't work: familymembers (dependantid) ---------------- AKI00001 coast (memberid, consultation, laboratory) ---------------- AKI00001, 4, 4 AKI00001, 4, 15 riftvalley (memberid, consultation, laboratory) ---------------- AKI00001, 2, 6 AKI00001, 2, 9 SELECT * FROM familymembers fm INNER JOIN coast c ON fm.dependantid = coast.memberid INNER JOIN riftvalley r ON fm.dependantid = riftvalley.memberid WHERE fm.dependantid = 'AKI00001'; -------------------------------------------------------------- (fm.dependantid, c.memberid, c.consultation, c.laboratory, r.memberid, r.consultation, r.laboratory) -------------------------------------------------------------- AKI00001,AKI00001, 4, 4, AKI00001, 2, 6 AKI00001,AKI00001, 4, 4, AKI00001, 2, 9 AKI00001,AKI00001, 4, 15, AKI00001, 2, 6 AKI00001,AKI00001, 4, 15, AKI00001, 2, 9 First, the column names in Jigal's query will be ambiguous as both `coast` and `riftvalley` provide columns called `consultation` and `laboratory` to the query. Second, because of the Cartesian product used to compute the JOINed dataset, you wind up with duplicates of the rows from both `coast` and `riftvalley`. The final SUM() could be off by some multiple based on the numbers of rows in each table. This is a tricky problem to solve because it requires a SUM() of a SUM(). The results of the first SUM() queries, I guess you could refer to them as subtotals, are computed on a per-table basis (each table representing a service area) and provide a single row of data as their result (you could expand the query to use a GROUP BY and process multiple `dependantid`s at once but that would just muddy this particular example). These subtotal rows need to be added together to produce a "grand total". The "store the subtotals in a temporary table" method is the one most compatible with the most MySQL installations (especially with those that do not have subqueries and "anonymous views") (I will revert to using the original queries AND I will rewrite them to NOT use the comma-separated, implicit INNER JOIN syntax) The first step is to collect all of your regional subtotals into a single list. I chose to use a temporary table: CREATE TEMPORARY TABLE tmpTotals SELECT nairobi.memberid, sum(consultation)+ sum(laboratory) as subtotal FROM nairobi INNER JOIN familymembers ON familymembers.dependantid = nairobi.memberid WHERE familymembers.memberid = "AKI00001"; INSERT tmpTotals (memberid, subtotal) SELECT coast.memberid, sum(consultation)+ sum(laboratory) as subtotal FROM coast INNER JOIN familymembers ON familymembers.dependantid = coast.memberid WHERE familymembers.memberid = "AKI00001"; INSERT tmpTotals (memberid, subtotal) SELECT riftvalley.memberid, sum(consultation)+ sum(laboratory) as subtotal FROM riftvalley INNER JOIN familymembers ON familymembers.dependantid = riftvalley.memberid WHERE familymembers.memberid = "AKI00001"; (NOTE: it would have been possible to use a single UNION query and reduce this step to a single statement but I don't know if David has UNIONs available) Now it's academic to use the data in the temporary table to provide the grand total SELECT memberid, sum(subtotal) as grandtotal FROM tmpTotals GROUP BY memberid; Of course, when you are through with it, you should always destroy a temporary table (don't rely on your OS or MySQL to do it for you, it may never get around to it and you could run low on resources) DROP TABLE tmpTotals; I know David wanted a single-statement method of solving this query (and one may be available) but I cannot predict what version MySQL he is running and this technique will find the data he wants and it will be FAST. For one person we should see response times under a second. For 100000 `memberid`s this may take up to 10 or 20 seconds to compute and for a few million people, it may take a few minutes (even on modest equipment). Shawn Green Database Administrator Unimin Corporation - Spruce Pine