简体   繁体   English

mysql 内部连接表上的左连接

[英]Left join on the inner join table for mysql

I have three tables Table A, Table B and Table C. My original query was我有三个表表 A、表 B 和表 C。我原来的查询是

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.此查询正在考虑所有具有“准备预订”值的里程碑,并且 TotalAmount 是根据不同日期范围内的 ClientID 和 Union 分组汇总的。

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.我喜欢有表 A 中“准备预订”的所有记录,并且只有表 A 中满足表(B 和 C)TableB.HexaID <> '' 和 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.通常,“Group by”子句尝试按不属于聚合的所有内容进行分组。 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.在您的原始查询中,您对客户端 ID 进行了分组,但您还返回了“B”表 ID 和里程碑日期(基于日期/时间的日期可能不会重复,因为您在时间戳列测试到分钟: 第二也是。

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).现在,JOINing…表 A 到 B 在常见的“id”列上很容易,但在表 B 中你只想要非空的 HexaID 值,所以我也添加了“AND”子句(而不是什么你有第二个 WHERE 子句)。

The last JOIN for Table C you had as INNER JOIN, but from table B was left-join.表 C 的最后一个 JOIN 为 INNER JOIN,但来自表 B 是左连接。 This would have resulted in a net INNER join since the third level "C" was inner, thus would force "B" being required.这将导致净 INNER 连接,因为第三级“C”在内部,因此将强制要求“B”。 To resolve these individually, I used transitive property.. Since A.id = B.id and B.id = C.ID, then A.ID = C.ID.为了单独解决这些问题,我使用了传递属性.. 因为 A.id = B.id 和 B.id = C.ID,那么 A.ID = C.ID。 So I was able to directly join A to C without B in a left and then inner join.所以我能够直接将 A 连接到 C 而没有 B 在左边然后内部连接。

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.使用您的判断来确认应如何解决这些表,因为通用的“表 A、B、C”没有提供真实的上下文,您应该在将来提供更现实的上下文。

The where clause, mostly untouched with few exceptions. where 子句,除了少数例外,几乎没有受到影响。 I personally don't like BETWEEN and changed to >= [one date] and LESS THAN [ending date].我个人不喜欢 BETWEEN 并更改为 >= [one date] 和 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.因此,在您查找 '2020-01-23 00:00:00' 上/之后的示例中,将时间部分关闭是同一回事。 However, your ending time such as the between AND date of 2020-01-28 23:59:59 would become Date < '2020-01-29'.但是,您的结束时间(例如 2020-01-28 23:59:59 之间的 AND 日期)将变为 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.因此,它明确包含 2020 年 1 月 28 日至并包括任何时间部分 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.日期的 where 子句包括整个期间与单独的选择/联合。 The SUM() has now become a SUM( case/when ) condition so it only sums based on the qualified dates. SUM() 现在已成为 SUM( case/when ) 条件,因此它仅根据限定日期求和。

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).关于连接辅助表(B 和 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.如果表 B 和 C 可以分别有多行,那么您的聚合将是笛卡尔结果的结果,并且可以/将被夸大。 Ex One Client, Table B ID... and Table B has 3 records with different hexaID values. Ex One Client, Table B ID... 和 Table B 有 3 个具有不同 hexaID 值的记录。 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.那么单个 A 金额 10 美元现在可以变成 30 美元,因为它符合表 B 中的每一行......如果表 C 中有多个记录,可以将 30 美元变成 60 美元、90 美元或更多,作为基于“B”记录的倍数. 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.不要让我们猜测辅助表的上下文,它们是 1:1、1:many 关系等。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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