【问题标题】:In SQL, Main table should match with lookup table for the multiple columns在 SQL 中,主表应与多列的查找表匹配
【发布时间】:2018-12-11 02:20:57
【问题描述】:

主表应该与给定列的查找表匹配,如果它不匹配并且查找表有任何空值,那么它应该与空值匹配(这里 null = 任何值)

场景

CREATE TABLE dbo.MAIN_TABLE (
NAMEID VARCHAR(50) NOT NULL,
COL1 VARCHAR(50) NULL,
COL2 VARCHAR(50) NULL,
COL3 VARCHAR(50) NULL,
COL4 VARCHAR(50) NULL,
CONSTRAINT PK_MAIN_TABLE PRIMARY KEY (NAMEID)
)

CREATE TABLE dbo.LOOKUP_TABLE (
COL1 VARCHAR(50) NULL,
COL2 VARCHAR(50) NULL,
COL3 VARCHAR(50) NULL,
COL4 VARCHAR(50) NULL,
RES_COL VARCHAR(50) NOT NULL
)

TRUNCATE TABLE dbo.LOOKUP_TABLE
INSERT INTO dbo.LOOKUP_TABLE VALUES('AA','BB', 'CC', NULL, 'Rule1')
INSERT INTO dbo.LOOKUP_TABLE VALUES('AA','BB', NULL, NULL, 'Rule2')
INSERT INTO dbo.LOOKUP_TABLE VALUES('AA',NULL, NULL, NULL, 'Rule3')
INSERT INTO dbo.LOOKUP_TABLE VALUES(NULL,NULL, NULL, NULL, 'Rule4')

TRUNCATE TABLE dbo.MAIN_TABLE
INSERT INTO dbo.MAIN_TABLE VALUES('NameId1','AA','BB', 'CC', 'DD' )
INSERT INTO dbo.MAIN_TABLE VALUES('NameId2','AA','BB', 'CC', NULL )
INSERT INTO dbo.MAIN_TABLE VALUES('NameId3','AA','BB', NULL, NULL )
INSERT INTO dbo.MAIN_TABLE VALUES('NameId4','AA', NULL, NULL, NULL )

INSERT INTO dbo.MAIN_TABLE VALUES('NameId5',NULL,'BB', 'CC', 'DD' )
INSERT INTO dbo.MAIN_TABLE VALUES('NameId6',NULL,NULL, 'CC', 'DD' )

预期结果

NAMEID  |  RES_COL
-----------------
NameId1 | Rule1
NameId2 | Rule1
NameId3 | Rule2
NameId4 | Rule3
NameId5 | Rule4
NameId6 | Rule4

我尝试了类似下面的查询,但它返回的重复行包含所有其他值

SELECT MN.NAMEID, MAP.RES_COL  FROM MAIN_TABLE MN
CROSS APPLY
(
  SELECT * FROM LOOKUP_TABLE LKP
  WHERE  
   ( CHECKSUM(MN.COL1) = CHECKSUM(LKP.COL1) OR LKP.COL1 IS NULL )
  AND
   ( CHECKSUM(MN.COL2) = CHECKSUM(LKP.COL2) OR LKP.COL2 IS NULL)
  AND
   ( CHECKSUM(MN.COL3) = CHECKSUM(LKP.COL3) OR LKP.COL3 IS NULL)
  AND
   ( CHECKSUM(MN.COL4) = CHECKSUM(LKP.COL4) OR LKP.COL4 IS NULL )
) MAP

ORDER BY MN.NAMEID ASC

【问题讨论】:

    标签: sql sql-server tsql


    【解决方案1】:

    由于 NULL = 匹配任何规则,您会获得多个匹配项。所以对于任何名称,Rule4 肯定会匹配,因为它对于所有列都是 NULL

    如果您只想要最佳匹配,请使用 TOP 1ORDER BY

    SELECT  *
    FROM    dbo.MAIN_TABLE m
            OUTER APPLY
            (
                SELECT  TOP 1 *
                FROM    dbo.LOOKUP_TABLE l
                WHERE   (l.COL1 = m.COL1 OR l.COL1 IS NULL)
                AND     (l.COL2 = m.COL2 OR l.COL2 IS NULL)
                AND     (l.COL3 = m.COL3 OR l.COL3 IS NULL)
                AND     (l.COL4 = m.COL4 OR l.COL4 IS NULL)
                ORDER BY 
                    CASE WHEN l.COL1 IS NOT NULL THEN 1 ELSE 2 END
                +   CASE WHEN l.COL2 IS NOT NULL THEN 1 ELSE 2 END
                +   CASE WHEN l.COL3 IS NOT NULL THEN 1 ELSE 2 END
                +   CASE WHEN l.COL4 IS NOT NULL THEN 1 ELSE 2 END
            ) l
    

    您使用 CHECKSUM() 而不是简单相等的 = 的任何特殊原因?

    【讨论】:

    • 我用校验和匹配NULL = NULL,比较值也很清楚。
    • 我不认为checksum() 保证给你一个独特的价值。我会做一个= 比较以保存
    • 当然,会检查的。而且,谢谢你的完美回答,你拯救了我的一天:)
    猜你喜欢
    • 1970-01-01
    • 2022-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多