使用SQL基于多个条件匹配2个相互不同的表中的记录

时间:2014-09-25 17:43:21

标签: sql sql-server

我正在尝试为一项研究建立一个数据集,我将成员分为两组,让他们称之为Hatfields和McCoys。 Hatfields比McCoys更多,我希望将每个Hatfield与我在McCoys中定义为足够相似的人匹配。我希望所有的比赛都是1-1。每个哈特菲尔德应该与1个麦考伊匹配,并且不应该匹配不止一次的麦考伊。可能会有一些多重匹配,但我想消除这些。我并不挑剔最好的"匹配,只是它是一场比赛。

会员日期分数
A 2/1/2014 1.00
B 4/4/2014 1.50
C 9/15/2014 1.00

会员Start_Date End_Date得分
D 1/1/2014 12/31/2014 1.00
E 6/1/2014 12/31/2014 0.50
F 1/1/2014 5/31/2014 1.50
G 1/1/2014 12/31/2014 1.00
H 8/1/2014 12/31/2014 1.00

上表显示了一个示例(抱歉格式不佳)。我希望将每个ABC与DEFGH中的一个匹配,我的标准是(1)ABC的日期在第二个表中的开始日期和结束日期之间,以及(2)分数匹配。

我考虑过尝试对每个表进行排序,然后按照索引字段进行操作。我可以在每个表上创建一个索引字段,然后如果第一个表中的第一个记录与第二个表中的第三个记录匹配,我会知道所有未来的匹配都将具有index_2>那会阻止任何人重复使用。

我不能完全把它放在一起。

感谢您的帮助!我喜欢学习SQL并欣赏新技巧!

1 个答案:

答案 0 :(得分:0)

djm50,

我无法在一个SQL语句中执行此操作,这应该可以为您提供所需的内容。

'#MatchedRows'包含与选择标准匹配的两个表的所有字段。在光标内部我跟踪已经使用过的成员,这是第一次,我将行#添加到'#SelectedRows'表中。我在MatchedRows和SelectedRows上进行内部联接,以获得您想要的效果。

DECLARE @row_number INT
    ,@member1 VARCHAR(1)
    ,@member2 VARCHAR(1);

IF OBJECT_ID('tempdb..#UsedMember') IS NOT NULL
    DROP TABLE #UsedMember;

IF OBJECT_ID('tempdb..#SelectedRows') IS NOT NULL
    DROP TABLE #SelectedRows;

IF OBJECT_ID('tempdb..#MatchedRows') IS NOT NULL
    DROP TABLE #MatchedRows;

Create Table #UsedMember ( Member varchar(1) );
Create Table #SelectedRows ( rowId int );

SELECT ROW_NUMBER() OVER (
        ORDER BY T1.MEMBER
        ) AS Row
    ,T1.Member T1_Member
    ,T1.DATE T1_Date
    ,T1.Score T1_Score
    ,T2.[Member] [T2_Member]
    ,T2.[StartDate] [T2_StartDate]
    ,T2.[EndDate] [T2_EndDate]
    ,T2.[Score] [T2_Score]
INTO #MatchedRows
FROM TableABC T1
    ,TableDEFG T2
WHERE (
        T1.DATE BETWEEN T2.StartDate
            AND T2.EndDate
        )
    AND T1.Score = T2.Score


--  select * from #MatchedRows

DECLARE member_cursor CURSOR
FOR
SELECT T1.Row AS Row
    ,T1.T1_Member AS Member1
    ,T1.T2_Member AS Member2
FROM #MatchedRows T1

OPEN member_cursor

FETCH NEXT
FROM member_cursor
INTO @row_number
    ,@member1
    ,@member2

WHILE @@FETCH_STATUS = 0
BEGIN
    PRINT '-';

    IF NOT EXISTS (
            SELECT 'x'
            FROM #UsedMember
            WHERE #UsedMember.Member = @member1
                OR #UsedMember.Member = @member2
            )
    BEGIN
        INSERT INTO #UsedMember (Member)
        VALUES (@member1);

        INSERT INTO #UsedMember (Member)
        VALUES (@member2);

        INSERT INTO #SelectedRows (rowId)
        VALUES (@row_number);
    END

    FETCH NEXT
    FROM member_cursor
    INTO @row_number
        ,@member1
        ,@member2
END

CLOSE member_cursor;

DEALLOCATE member_cursor;

SELECT *
FROM #MatchedRows
INNER JOIN #SelectedRows ON (#MatchedRows.Row = #SelectedRows.rowId)