【问题标题】:MSSQL conditional join conditionMSSQL 条件连接条件
【发布时间】:2017-11-29 19:04:03
【问题描述】:

我在加入时遇到了一些麻烦,希望社区能够提供帮助。我正在尝试在 transtypeID 列上加入两个表 TRANSACTIONS 和 TRANSTYPES。很容易。但是交易可以是国外的也可以是国内的,如 foreign_account 列所示。事务类型可以是外部的或国内的,并且在 TRANSTYPES 表中可以有多个行。

我正在寻找一个尽可能匹配 ID 上的 TRANSACTIONS 和 TRANSTYPES 以及 foreign_account=foreign_account(x=x 或 null=null)的联接。如果foreign_account 上没有匹配,则取transtypeID 匹配的行,不关注foreign_account 列。

表设置:

CREATE TABLE ##TRANSTYPES
        (transtypeID int,
        tt_name VARCHAR(50),
        foreign_account VARCHAR(5),
        additional_info VARCHAR(20))

INSERT INTO ##TRANSTYPES
    VALUES
    (1000,NULL,102.00),
    (1002, NULL, 103.00),
    (1002, 'x', 104.00),
    (1003, 'x', 105.00),
    (1003, 'x', 106.00), 
    (1003, NULL, 107.00),
    (1003, NULL, 108.00)
CREATE TABLE ##TRANSACTIONS
        (transtypeID int,
        foreign_account VARCHAR(5),
        balance DECIMAL(18,4))

INSERT INTO ##TRANSACTIONS
    VALUES  
        (1000,NULL,102.00 ),
        (1002, NULL, 103.00),
        (1002, 'x', 104.00),
        (1003, 'x', 105.00)

我从一个简单的连接开始,但我没有得到 1003 类型的事务。

SELECT *
FROM ##transtypes TT
FULL outer JOIN ##transactions TRN
    ON tt.transtypeid = trn.transtypeID 
WHERE
    (TRN.foreign_account = TT.foreign_account
    OR (TRN.foreign_account IS NULL AND tt.foreign_account IS NULL))

我有一种交叉应用的感觉,但我以前从未写过。我正在努力解决如何正确获取子查询的问题。我正在尝试在由 foreign_account 列排序的 TRANSTYPE 表上选择前 1 个,但到目前为止还没有运气。

提前谢谢你。

【问题讨论】:

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


    【解决方案1】:

    从转换 ID 上的连接开始。然后对你的行进行排名,只保留更好的匹配(即相同的 foreign_account 可用):

    SELECT tt_name, additional_info, transtypeID, foreign_account, balance
    FROM
    (
      SELECT 
        tt.tt_name,
        tt.additional_info, 
        trn.transtypeID,
        trn.foreign_account,
        trn.balance,
        row_number() 
          over (partition by tt.transtypeID, tt.tt_name 
                order by case when (trn.foreign_account = tt.foreign_account)
                                or (trn.foreign_account is null and tt.foreign_account is null)
                                   then 1
                                   else 2
                         end) as rn
      FROM ##transtypes tt 
      JOIN ##transactions trn ON trn.transtypeID = tt.transtypeID
    ) ranked
    WHERE rn = 1;
    

    【讨论】:

    • Thorsten - 感谢您的帮助。这让我更接近,但没有给我 1002 类型的第二笔交易。
    • 哦,对不起,你是对的。我不能根据transtypeID 寻找最佳匹配,而是根据transtypeID+ tt_name 寻找最佳匹配。我已经更正了我的查询。
    • 索斯滕 - 这很棒。非常感谢您的宝贵时间。
    • 我认为当您在同一个 transtypeID 和同一个 foreign_account 标志上有多个事务时,这种情况就会开始崩溃。你只会得到第一名。如果您添加到##transactions 表中,(1003, 'x', 106.00), (1003, NULL, 107.00),您将丢失 $105,$106 的交易。
    • 你让它看起来像foreign_account为null的记录和每transtypeID的一个'x'记录。如果可以有更多,那么您不是在寻找单一的最佳记录。将ROW_NUMBER 替换为RANK 以考虑更多匹配项。我希望就是这样。 foreign_account 只能为 null 或 'x',对吗?
    【解决方案2】:

    你可以使用 UNION ALL

    SELECT  tt.tt_name,
        tt.additional_info, 
        trn.transtypeID,
        trn.foreign_account,
        trn.balance
    FROM ##TRANSTYPES tt INNER JOIN ##TRANSACTIONS trn ON tt.foreign_account = trn.foreign_account
    
    UNION ALL
    
    SELECT  tt.tt_name,
        tt.additional_info, 
        trn.transtypeID,
        trn.foreign_account,
        trn.balance
    FROM ##TRANSTYPES tt INNER JOIN ##TRANSACTIONS trn ON tt.transTypeID = trn.transTypeID
    WHERE tt.foreign_account <> trn.foreign_account
    OR (TRN.foreign_account IS NULL AND tt.foreign_account IS NULL)
    

    【讨论】:

    • 大卫 - 这似乎是一个很好的解决方案。它在添加交易和重复时成立。非常感谢
    猜你喜欢
    • 2017-04-17
    • 2013-05-18
    • 2014-12-25
    • 2011-11-08
    • 2011-03-29
    • 2018-06-25
    • 2014-06-07
    • 2011-09-04
    相关资源
    最近更新 更多