简体   繁体   中英

Left join on the inner join table for mysql

I have three tables Table A, Table B and Table C. My original query was

SELECT  TableA.ClientID,  TableA.id,  TableA.Milestone, SUM(TableA.totalamount)
FROM  TableA 
WHERE TableA.Milestone IN('Ready to Book') 
AND TableA.MilestoneDate BETWEEN'2020-01-29 00:00:00'  AND '2020-01-29 23:59:59'  
AND TableA.Type IN( 'Purchase','Refinance','Purchase / Refinance','Variation - 
Docs Only','Upstamp','Refinance (unattended)' ) 
GROUP BY TableA.clientID
UNION 
SELECT  TableA.ClientID,  TableA.id,  TableA.Milestone, SUM(TableA.totalamount)
FROM  TableA 
WHERE TableA.Milestone IN('Ready to Book') 
AND TableA.MilestoneDate BETWEEN '2020-01-23 00:00:00'  and '2020-01-28 23:59:59' 
AND TableA.Type IN( 'Purchase','Refinance','Purchase / Refinance','Variation - 
Docs Only','Upstamp','Refinance (unattended)' ) 
GROUP BY TableA.clientID
UNION
SELECT  TableA.ClientID,  TableA.id,  TableA.Milestone, SUM(TableA.totalamount)
FROM  TableA 
WHERE TableA.Milestone IN('Ready to Book') 
AND TableA.MilestoneDate BETWEEN '2019-12-15 00:00:00'   and '2020-01-22 23:59:59' 
AND TableA.Type IN( 'Purchase','Refinance','Purchase / Refinance','Variation - 
Docs Only','Upstamp','Refinance (unattended)' ) 
GROUP BY TableA.clientID
UNION
SELECT  TableA.ClientID,  TableA.id,  TableA.Milestone, SUM(TableA.totalamount)
FROM  TableA 
WHERE TableA.Milestone IN('Ready to Book') 
AND TableA.`MilestoneDate` BETWEEN '2019-12-12 00:00:00'   and '2020-01-14 23:59:59'    
AND TableA.Type IN( 'Purchase','Refinance','Purchase / Refinance','Variation - 
Docs Only','Upstamp','Refinance (unattended)' ) 
GROUP BY TableA.clientID
UNION
SELECT  TableA.ClientID,  TableA.id,  TableA.Milestone, SUM(TableA.totalamount)
FROM  TableA 
WHERE TableA.Milestone IN('Ready to Book') 
AND TableA.MilestoneDate <= '2019-12-14 23:59:59'   
AND TableA.Type IN( 'Purchase','Refinance','Purchase / Refinance','Variation - 
Docs Only','Upstamp','Refinance (unattended)' ) 
GROUP BY TableA.clientID

This query is considering all the Milestone with Value 'Ready To Book' and TotalAmount is Summed based on group by ClientID and Union on different date ranges.

I am trying to modify this query to consider the milestone values both 'Ready To Book' and'Already Booked'. I like to have all records of 'Ready To Book' from table A and only those records of 'Already Booked' from tableA which satisfies the conditions from tables (B and C) TableB.HexaID <> '' and TableC.AcceptedDate IS NULL.

So my query should be

SELECT  TableA.ClientID,  TableA.id,  TableA.Milestone, SUM(TableA.totalamount)
FROM  TableA 
Left JOIN (TableB ON TableA.id = TableB.id
INNER JOIN TableC on TableC.id = tableB.id WHERE TableB.HexaID <> ''And TableC.AcceptedDate IS NULL)
WHERE TableA.Milestone IN('Ready to Book', 'Already Booked') 
AND TableA.MilestoneDate BETWEEN'2020-01-29 00:00:00'  AND '2020-01-29 23:59:59'  
AND TableA.Type IN( 'Purchase','Refinance','Purchase / Refinance','Variation - 
Docs Only','Upstamp','Refinance (unattended)' ) 
GROUP BY TableA.clientID
UNION
SELECT  TableA.ClientID,  TableA.id,  TableA.Milestone, SUM(TableA.totalamount)
FROM  TableA 
Left JOIN TableB ON TableA.id = TableB.id
INNER JOIN (TableC on TableC.id = tableB.id WHERE TableB.HexaID <> ''And TableC.AcceptedDate IS NULL)
WHERE TableA.Milestone IN('Ready to Book', 'Already Booked') 
AND TableA.`MilestoneDate` BETWEEN '2020-01-23 00:00:00'  and '2020-01-28 23:59:59'  
AND TableA.Type IN( 'Purchase','Refinance','Purchase / Refinance','Variation - 
Docs Only','Upstamp','Refinance (unattended)' ) 
GROUP BY TableA.clientID UNION etc

I am getting syntax error. How this can be achieved. Please guide

Here is a revised version of your query. Typically "Group by" clauses try to group by everything that is not part of an aggregate. In your original query, you were grouping the client id, but you were also returning the "B" table ID and the Milestone date (which based on date/time probably would not be duplicated as you indicate in your timestamp columns testing to the minute:second as well.

So, I removed those extra columns as it appears your primary consideration is the group by the client.

Next, ignore the rest of the columns for now I have in summation, I added more that you MIGHT be interested in and figured I would just offer up-front.

Now, the JOINing… Table A to B was easy enough on the common "id" column, but also in table B you only wanted non-blank HexaID values, so I added the "AND" clause to that as well (instead of what you had as second WHERE clause).

The last JOIN for Table C you had as INNER JOIN, but from table B was left-join. This would have resulted in a net INNER join since the third level "C" was inner, thus would force "B" being required. To resolve these individually, I used transitive property.. Since A.id = B.id and B.id = C.ID, then A.ID = C.ID. So I was able to directly join A to C without B in a left and then inner join.

Use your judgement on confirmation of how these tables should be resolved as generic "Table A, B, C" does not give true context and you SHOULD give more realistic context in the future.

The where clause, mostly untouched with few exceptions. I personally don't like BETWEEN and changed to >= [one date] and LESS THAN [ending date]. So, in the example of you looking for things on/after '2020-01-23 00:00:00', leaving the time portion off is the same thing. However, your ending time such as the between AND date of 2020-01-28 23:59:59 would become Date < '2020-01-29'. So it explicitly is inclusive of everything on 2020-01-28 up to and including any time portion 23:59:59. Net result same, but to me and possibly others more explicit than wrapping head around times.

Finally, the summing. You are looking for amounts per client per their respective milestone date/time periods. The where clause on the date is inclusive of the entire period in question vs separate select/unions. The SUM() has now become a SUM( case/when ) condition so it only sums based on the qualified dates.

To give you some extra, I added an extra level to show totals per period and purpose (Ready to book vs Already Booked). So now you have each component individually and grand-totals on a single row per client vs multiple rows per client. Again, just an option of aggregating. What if a client has no activity in one time period and does in another... and different clients could have opposite or in both. This also allows the rollup per client on same row.

SELECT  
        A.ClientID,  

        SUM( case when A.Milestone = 'Ready to Book'
                    AND A.MilestoneDate >= '2020-01-29' AND A.MilestoneDate < '2020-01-30'
                then A.totalamount else 0 end ) ReadyToBookMilestone1,
        SUM( case when A.Milestone = 'Ready to Book'
                    AND A.MilestoneDate >= '2020-01-23' AND A.MilestoneDate < '2020-01-29'
                then A.totalamount else 0 end ) ReadyToBookMilestone2,
        SUM( case when A.Milestone = 'Ready to Book'
                then A.totalamount else 0 end ) ReadyToBookTotalMilestone,

        SUM( case when A.Milestone = 'Already Booked'
                    AND A.MilestoneDate >= '2020-01-29' AND A.MilestoneDate < '2020-01-30'
                then A.totalamount else 0 end ) AlreadyBookedMilestone1,
        SUM( case when A.Milestone = 'Already Booked'
                    AND A.MilestoneDate >= '2020-01-23' AND A.MilestoneDate < '2020-01-29'
                then A.totalamount else 0 end ) AlreadyBookedMilestone2,
        SUM( case when A.Milestone = 'Already Booked'
                then A.totalamount else 0 end ) AlreadyBookedTotalMilestone,

        SUM( case when A.MilestoneDate >= '2020-01-29' AND A.MilestoneDate < '2020-01-30'
                then A.totalamount else 0 end ) TotalMilestone1,
        SUM( case when A.MilestoneDate >= '2020-01-23' AND A.MilestoneDate < '2020-01-29'
                then A.totalamount else 0 end ) TotalMilestone2,
        SUM(A.totalamount)  TotalAllMilestones
    FROM 
        TableA A
            Left JOIN TableB B
                ON A.id = B.id
                AND B.HexaID <> ''
            JOIN TableC C
                on A.id = C.id 
                And C.AcceptedDate IS NULL
    WHERE 
            A.Milestone IN ('Ready to Book', 'Already Booked') 
        AND A.Type IN ( 'Purchase','Refinance','Purchase / Refinance','Variation - Docs Only','Upstamp','Refinance (unattended)' ) 
        AND A.MilestoneDate>= '2020-01-23'
        AND A.MilestoneDate < '2020-01-30'
    GROUP BY 
        TableA.clientID

One final note on summation when joining secondary tables (B and C). If tables B and C can each respectively have multiple rows, then your aggregates will be the result of a Cartesian result and can/will be overstated. Ex One Client, Table B ID... and Table B has 3 records with different hexaID values. Then a single A amount of $10 COULD now become $30 since it qualifies with EACH row in table B... If multiple records in table C, could turn that $30 into $60, $90, or more as a multiple based on "B" records. This is where it is more critical to provide more explicit details of each table in the future. Don't make us guess at context of secondary tables, are they 1:1, 1:many relationships, etc.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM