SQL联盟与“排名”

时间:2017-12-15 11:31:54

标签: sql sql-server tsql

我正在编写一个查询来搜索特定用户的表格,这将提供完全匹配和潜在匹配。

基本上,用户的电子邮件地址是唯一的,因此我不需要返回超过这一行,但除此之外,我需要返回所有潜在用户,他们的匹配程度可能是“匹配”。

我希望查询尽可能高效,并且为此我避免了游标,因为我觉得它不是必要的。这是我当前查询的一个示例。

    SELECT 
            tt.userId,
            tt.UserName,
            ad.*,
            1 AS 'Rank'
        FROM
            Users.User tt
        LEFT JOIN
            General.[Address] ad ON tt.AddressId = ad.AddressId
        WHERE
            tt.EmailAddress = @EmailAddress
    UNION

        SELECT 
            tt.userId,
            tt.UserName,
            ad.*,
            2 AS 'Rank'
        FROM
            Users.User tt
        LEFT JOIN
            General.[Address] ad ON tt.AddressId = ad.AddressId
        WHERE
            tt.LastName = @LastName
            AND tt.BirthDate = @DOB

显然,这里的主要缺陷是,如果电子邮件地址匹配,同一用户也将出现在第二个查询中,依此类推。另外,由于我需要对这些搜索进行排名,因此union不会将这些行匹配为重复,因此我会多次返回相同的用户。

非常感谢任何建议。

2 个答案:

答案 0 :(得分:2)

您根本不需要/users/{id}/attribute

union

显然,添加其他条件很容易,例如当所有三列都匹配时的新排名。

答案 1 :(得分:0)

这是未经测试的,因为没有样本数据,但我相信这会起作用。如果没有,请发布一些DDL和消耗品样本数据:

@OneToMany(fetch = FetchType.LAZY)

WITH Results AS( SELECT tt.UserID, tt.UserName, ad.*, DENSE_RANK() OVER (ORDER BY CASE WHEN tt.EmailAddress = @EmailAddress THEN 0 ELSE 1 END) AS RN FROM Users.[User] tt LEFT JOIN General.[Address] ad ON tt.AddressId = ad.AddressID WHERE tt.EmailAddress = @EmailAddress OR (tt.LastName = @LastName AND tt.BirthDate = @DOB)) SELECT * FROM Results WHERE RN = 1; 表示您最终得到2个组,但是,如果找不到电子邮件地址,则所有结果的最终结果为RN为1.否则,具有相同电子邮件地址的人将拥有RN为1,其余为2(意味着这些匹配不会显示在CTE之外的DENSE_RANK()子句中。