加入两个具有不同字段值的表

时间:2017-03-03 09:09:48

标签: sql-server sql-server-2008 inner-join

是否可以连接具有不同字段值的两个表?我正在使用MS SQL Server 2008。

表A(original image,感谢@EdwardRusu将图像翻译成文本):

+ ----- + --------- + -------- + ----------- + ------------------ + ---------------- + ----------- +
| RecID | Member ID | LoanType | LoanSubType | Application Number | Application Date | Loan Amount |
+ ----- + --------- + -------- + ----------- + ------------------ + ---------------- + ----------- +
| 3     | 00005     | Regular  |             | 201604002          | 2016-02-28       | 39864.00    |
| 185   | 00005     | Special  | Special ... | 201604183          | 2016-10-31       | 10000.00    |
| 318   | 00005     | Regular  |             | 201605063          | 2016-05-18       | 39864.00    |
| 427   | 00005     | Regular  |             | 201608021          | 2016-08-18       | 39872.00    |
| 486   | 00005     | Special  | Special ... | 201609044          | 2016-09-07       | 10000.00    |
| 589   | 00005     | Regular  |             | 201611008          | 2016-11-04       | 39872.00    |
| 689   | 00005     | Regular  |             | 201702004          | 2017-02-02       | 39872.00    |
+ ----- + --------- + -------- + ----------- + ------------------ + ---------------- + ----------- +

表B(original image):

+ --------------- + --------- + ------ + ----- + ---------- + -------- + -------- + -------- +
| ProjectAcctCode | Member ID | TMonth | TYear | TLastDate  | TDebit   | TCredit  | TBalance |
+ --------------- + --------- + ------ + ----- + ---------- + -------- + -------- + -------- +
| 105350500       | 00005     | 1      | 2017  | 2017-01-31 | 0.00     | 2952.00  | -2952.00 |
| 105350500       | 00005     | 5      | 2016  | 2016-05-31 | 73084.00 | 33220.00 | 39864.00 |
| 105350500       | 00005     | 6      | 2016  | 2016-06-30 | 0.00     | 2951.42  | -2952.42 |
| 105350500       | 00005     | 7      | 2016  | 2016-07-31 | 0.00     | 3014.14  | -3014.14 |
| 105350500       | 00005     | 8      | 2016  | 2016-08-31 | 39872.00 | 33905.26 | 5973.55  |
| 105350500       | 00005     | 9      | 2016  | 2016-09-30 | 0.00     | 2952.00  | -2952.00 |
| 105350500       | 00005     | 10     | 2016  | 2016-10-31 | 0.00     | 3014.73  | -3014.73 |
| 105350500       | 00005     | 11     | 2016  | 2016-11-30 | 39872.00 | 33905.26 | 5966.74  |
| 105351000       | 00005     | 1      | 2017  | 2017-01-31 | 0.00     | 975.03   | -975.03  |
| 105351000       | 00005     | 5      | 2016  | 2016-05-31 | 5000.00  | 1000.00  | 4000.00  |
| 105351000       | 00005     | 6      | 2016  | 2016-06-30 | 0.00     | 1000.00  | -1000.00 |
| 105351000       | 00005     | 7      | 2016  | 2016-07-31 | 0.00     | 1000.00  | -1000.00 |
| 105351000       | 00005     | 8      | 2016  | 2016-08-31 | 0.00     | 1000.00  | -1000.00 |
| 105351000       | 00005     | 9      | 2016  | 2016-09-30 | 10000.00 | 1000.00  | 9000.00  |
| 105351000       | 00005     | 10     | 2016  | 2016-10-31 | 0.00     | 955.82   | -955.82  |
| 105351000       | 00005     | 11     | 2016  | 2016-11-30 | 0.00     | 965.38   | -965.38  |
+ --------------- + --------- + ------ + ----- + ---------- + -------- + -------- + -------- +

我想通过MemberID,LoanType,ApplicationNo,ApplicationDate来分组TableB中的TBalance。应该基于LoanType和ProjAcctCode AND ApplicationDate和TLastDate连接这两个表。 LoanType和ProjAcctCode具有不同的值。但是,“REGULAR”Loantype等于“105350500”ProjAcctCode,“SPECIAL LoanType”相当于“105351000”ProjAcctCode。 ApplicationDate应小于或等于TLastDate。

因此,如果我将为“REGULAR”贷款类型生成记录,我应该有这样的事情(original image):

+ -------- + -------- + ------------- + --------------- + ---------- + ------------ + --------- + --------- +
| MemberID | LoanType | ApplicationNO | ApplicationDate | LoanAmount | ProjAcctCode | TLastDate | Balance   |
+ -------- + -------- + ------------- + --------------- + ---------- + ------------ + --------- + --------- +
| 000005   | Regular  | 201608021     | 8/18/2016       | 39,872.00  | 105350500    | 8/31/2016 | 39,871.44 |
+ -------- + -------- + ------------- + --------------- + ---------- + ------------ + --------- + --------- +

但是我的查询

SELECT a.MemberID,
    (SELECT TOP (1) ApplicationNo
        FROM TABLE A
        WHERE (MemberID = a.MemberID) AND    (ApplicationDate <= b.TLastDate)
        ORDER BY ApplicationNo DESC) AS ApplicationNo,
    (SELECT TOP (1) LoanAmount
        FROM TABLE A AS SAL_APPLICATION_HEADER_1
        WHERE (MemberID = a.MemberID) AND (ApplicationDate <= b.TLastDate)
        ORDER BY ApplicationNo DESC) AS LoanAmount,
    (SELECT TOP (1) ApplicationDate
        FROM TABLE A AS SAL_APPLICATION_HEADER_2
        WHERE (MemberID = a.MemberID)
            AND (ApplicationDate <= b.TLastDate)
        ORDER BY ApplicationNo DESC) AS ApplicationDate,
    vwSAL_Balance_SL_1.ProjAcctCode,
    b.TDebit,
    b.TCredit, 
    b.TBalance AS Balance,
    b.TLastDate
    FROM TABLE A AS a
    INNER JOIN TABLE B AS b ON a.MemberID = b.SLCode
    GROUP BY a.MemberID,
        b.TDebit, 
        b.TCredit,
        b.TBalance,
        b.ProjAcctCode,
        b.TLastDate
    HAVING (a.MemberID = N'00005') AND (b.TLastDate = '8/31/2016')

我得到了这个结果(original image):

+ -------- + ------------- + ---------- + --------------- + ------------ + -------- + -------- + -------- + ---------- + 
| MemberID | ApplicationNo | LoanAmount | ApplicationDate | ProjAcctCode | TDebit   | TCredit  | Balance  | TLastDate  |
+ -------- + ------------- + ---------- + --------------- + ------------ + -------- + -------- + -------- + ---------- + 
| 00005    | 201608021     | 39872.00   | 2016-08-18      | 105351000    | 0.00     | 1000.00  | -1000.00 | 2016-08-31 |
| 00005    | 201608021     | 39872.00   | 2016-08-18      | 105350500    | 39872.00 | 33898.45 | 5973.55  | 2016-08-31 |
+ -------- + ------------- + ---------- + --------------- + ------------ + -------- + -------- + -------- + ---------- + 

这可能太长但请求帮助。谢谢。

2 个答案:

答案 0 :(得分:0)

tl; dr 是的,有可能。最后的查询块将为您提供所需的内容。

是的,只要您知道两者之间存在某种相关性,就可以连接两个具有不同字段值的表。我将引导您完成连接语句的构造,该语句可以为您提供所需的内容。你需要三件事:

1)匹配MemberID和SLCode

2)匹配LoanType和ProjAcctCode

3)匹配日期


MemberID和SLCode

根据您上面的评论,我将假设SLCode与B中的MemberID相同。

select *
    from A
    inner join B
        on B.MemberID = A.MemberID -- or B.SLCode = A.MemberID


LoanType和ProjAcctCode

在此示例中,您希望在连接中使用case语句,例如

inner join B.ProjAcctCode = case A.LoanType when 'Regular' then 105350500 else 105351000 end

这表示如果LoanType是Regular,则只加入具有ProjAcctCode = 105350500的记录;否则加入具有ProjAcctCode 105351000的记录。(这里,LoanType只有两个状态,所以使用else子句捕获特殊贷款是完全没问题。如果有两个以上的状态,那么你必须使用其他条件。)

select *
    from A
    inner join B
        on B.MemberID = A.MemberID
        and B.ProjAcctCode = case A.LoanType when 'Regular' then 105350500 else 105351000 end


<强>日期

立即过滤日期过滤器。

select *
    from A
    inner join B
        on B.MemberID = A.MemberID
        and B.ProjAcctCode = case A.LoanType when 'Regular' then 105350500 else 105351000 end
        and A.ApplicationDate <= B.TLastDate


群组和汇总

现在您已正确连接表,您只需要进行分组和聚合。您可以对A中的任何内容进行分组,因为这些字段不会针对您想要的聚合进行更改,而您只需要对如何选择来自B的内容有点聪明。在您的问题中,它看起来像您想要的ProjAcctCode(这不会改变,因此我们也可以对此进行分组),TLastDate(这确实会改变,因此我们需要在某些条件上进行聚合)和TBalance(我们希望从中得到总和)。我假设您需要最新的TLastDate,因此您的查询将类似于

select  A.MemberID,
        A.LoanType,
        A.ApplicationNumber,
        A.ApplicationDate,
        [anything else you want from A],
        B.ProjAcctCode -- aggregate not needed because this doesn't change
        max(B.TLastDate) as TLastDate,
        sum(B.TBalance) as TBalance
    from A
    inner join B
        on B.MemberID = A.MemberID
        and B.ProjAcctCode = case A.LoanType when 'Regular' then 105350500 else 105351000 end
        and A.ApplicationDate <= B.TLastDate
    group by A.MemberID,
        A.LoanType,
        A.ApplicationNumber,
        A.ApplicationDate,
        [anything else you selected from A],
        B.ProjAcctCode

这将产生下表

+ -------- + -------- + ----------------- + --------------- + ------------ + ---------- + -------- +
| MemberID | LoanType | ApplicationNumber | ApplicationDate | ProjAcctCode | TLastDate  | TBalance |
+ -------- + -------- + ----------------- + --------------- + ------------ + ---------- + -------- +
| 00005    | Regular  | 201604002         | 2016-02-08      | 105350500    | 2017-01-31 | 36913.19 |
| 00005    | Special  | 201604183         | 2016-10-31      | 105351000    | 2017-01-31 | -2896.23 |
| 00005    | Regular  | 201605063         | 2016-05-18      | 105350500    | 2017-01-31 | 36913.19 |
| 00005    | Regular  | 201608021         | 2016-08-18      | 105350500    | 2017-01-31 | 3014.75  |
| 00005    | Special  | 201609044         | 2016-09-07      | 105351000    | 2017-01-31 | 6103.77  |
| 00005    | Regular  | 201611008         | 2016-11-04      | 105350500    | 2017-01-31 | 3014.74  |
+ -------- + -------- + ----------------- + --------------- + ------------ + ---------- + -------- +

注意:ApplicationNumber 201702004的贷款不会出现在最终结果中,因为它按日期过滤掉(即其申请日期大于B中的所有TLastDate)。

答案 1 :(得分:0)

我只是在查询中使用UNION(每个LoanType)来获得所需的结果。