Sql 加入优先标准?
我必须将表1中的每条记录与表2中最多一条记录进行匹配。 有一种更好的匹配方法(代码相等)和一种较差的匹配方法(在没有代码相等的情况下,让我们按代码排序并按索引匹配) 作为第一个近似值,我们假设执行此操作的代码可能如下所示:Sql 加入优先标准?,sql,sql-server-2005,join,Sql,Sql Server 2005,Join,我必须将表1中的每条记录与表2中最多一条记录进行匹配。 有一种更好的匹配方法(代码相等)和一种较差的匹配方法(在没有代码相等的情况下,让我们按代码排序并按索引匹配) 作为第一个近似值,我们假设执行此操作的代码可能如下所示: SELECT TABLE1.CODE AS CODE1, TABLE2.CODE AS CODE2 FROM (SELECT ROW_NUMBER() OVER(ORDER BY CODE) INDEX, CODE FROM TABLE1) T1 LEFT JOIN (SE
SELECT
TABLE1.CODE AS CODE1,
TABLE2.CODE AS CODE2
FROM
(SELECT ROW_NUMBER() OVER(ORDER BY CODE) INDEX, CODE FROM TABLE1) T1
LEFT JOIN
(SELECT ROW_NUMBER() OVER(ORDER BY CODE) INDEX, CODE FROM TABLE2) T2
ON
(T1.CODE=T2.CODE) --CODE equality
OR
(T1.INDEX=T2.INDEX) --CODE equality
让我们考虑这些表:
TABLE1 TABLE2
+------+ +------+
| CODE | | CODE |
+------+ +------+
| AAA | | BBB |
| BBB | | CCC |
| CCC | | DDD |
+------+ +------+
结果将是:
CODE1 CODE2
----- -----
AAA BBB -> matched because of INDEX equality
BBB BBB -> matched because of CODE equality
BBB CCC -> matched because of INDEX equality
CCC CCC -> matched because of CODE equality
CCC DDD -> matched because of INDEX equality
困难来了:我想表达这样一种观点,即尽管有两个匹配条件不是相互排斥的,但如果可能,第一个条件必须优先于第二个条件,并且只有当第一个条件失败时,才能对第二个条件进行评估
结果是:
CODE1 CODE2
----- -----
AAA DDD -> matched because of INDEX equality between the cast-off records not able to match better
(corrected from the previous version where AAA was said to match expectedly with BBB)
BBB BBB -> matched thanks to CODE equality, no need to match on INDEX
CCC CCC -> matched thanks to CODE equality, no need to match on INDEX
当然,我最好在一个查询中获得此行为,以避免使用多步骤脚本,因为:
- 你可以随意提出一个完全不同的问题:上面的问题只是为了说明总体思路,但显然不符合需要。因此,没有必要试图保留其结构
- 与希望执行多功能查询匹配相比,我并不真正关心性能。如果需要子查询,那就开始吧!;-)
思想是:尽可能多地匹配代码相等性,然后只考虑那些由第一匹配算法留下的与索引匹配的那些。这就是为什么AAA错误地期望与BBB(已经与另一个BBB匹配)匹配索引的原因。实际上,索引必须与另一个非代码匹配项(在这种情况下为DDD)匹配。
鉴于您的测试数据和预期结果,这将给出正确的结果;WITH T1 (row_id, code) AS (SELECT ROW_NUMBER() OVER (ORDER BY code) AS row_id, code FROM My_Table_1),
T2 (row_id, code) AS (SELECT ROW_NUMBER() OVER (ORDER BY code) AS row_id, code FROM My_Table_2)
SELECT
T1.code,
COALESCE(T2.code, T3.code)
FROM
T1
LEFT OUTER JOIN T2 ON T2.code = T1.code
LEFT OUTER JOIN T2 AS T3 ON T2.row_id IS NULL AND T3.row_id = T1.row_id
根据您的测试数据和预期结果,这将给出正确的结果
;WITH T1 (row_id, code) AS (SELECT ROW_NUMBER() OVER (ORDER BY code) AS row_id, code FROM My_Table_1),
T2 (row_id, code) AS (SELECT ROW_NUMBER() OVER (ORDER BY code) AS row_id, code FROM My_Table_2)
SELECT
T1.code,
COALESCE(T2.code, T3.code)
FROM
T1
LEFT OUTER JOIN T2 ON T2.code = T1.code
LEFT OUTER JOIN T2 AS T3 ON T2.row_id IS NULL AND T3.row_id = T1.row_id
我尝试了Oracle,但想法如下:
with t1 as (select 1 id,'AAA' col from dual union all
select 2, 'BBB' from dual union all
select 3, 'CCC' from dual ),
t2 as (select 1 id,'BBB' col from dual union all
select 2, 'CCC' from dual union all
select 3, 'DDD' from dual )
---
SELECT t1.col col1, t2.col col2
FROM t1, t2
WHERE (t1.id = t2.id OR t1.col = t2.col)
AND (t2.id = 1 OR t1.col = t2.col)
结果:
COL1 COL2
--- ---
AAA BBB
BBB BBB
CCC CCC
我尝试了Oracle,但想法如下:
with t1 as (select 1 id,'AAA' col from dual union all
select 2, 'BBB' from dual union all
select 3, 'CCC' from dual ),
t2 as (select 1 id,'BBB' col from dual union all
select 2, 'CCC' from dual union all
select 3, 'DDD' from dual )
---
SELECT t1.col col1, t2.col col2
FROM t1, t2
WHERE (t1.id = t2.id OR t1.col = t2.col)
AND (t2.id = 1 OR t1.col = t2.col)
结果:
COL1 COL2
--- ---
AAA BBB
BBB BBB
CCC CCC
好的,我知道了。
我把答案贴出来,以防有人对它感兴趣。
它可以根据最终的需要进行调整,但想法是存在的(我稍微更改了字段/常量的名称:它更接近真实的名称,并帮助我找到了解决方案,否则就太理论化了)
结果:
cod_uc cod_cnt matched_with
------ ------- ------------
A NULL D
B B B
C C C
NULL D A
NULL E NULL
好的,我知道了。
我把答案贴出来,以防有人对它感兴趣。
它可以根据最终的需要进行调整,但想法是存在的(我稍微更改了字段/常量的名称:它更接近真实的名称,并帮助我找到了解决方案,否则就太理论化了)
结果:
cod_uc cod_cnt matched_with
------ ------- ------------
A NULL D
B B B
C C C
NULL D A
NULL E NULL
初始数据:
; WITH
T1 (CODE) AS
( SELECT 'AAA' CODE UNION
SELECT 'BBB' UNION
SELECT 'CCC'
)
, T2 (CODE) AS
( SELECT 'BBB' CODE UNION
SELECT 'CCC' UNION
SELECT 'DDD'
)
帮助表:
, FULLT (code1, code2) AS
( SELECT T1.CODE AS code1
, T2.CODE AS code2
FROM T1
FULL OUTER JOIN T2
ON T1.CODE = T2.CODE
)
, INNERT (code1, code2) AS
( SELECT code1
, code2
FROM FULLT
WHERE code1 = code2
)
, LEFTT (code1, rn) AS
( SELECT code1
, ROW_NUMBER() OVER(ORDER BY code1) AS rn
FROM FULLT
WHERE code2 IS NULL
)
, RIGHTT (code2, rn) AS
( SELECT code2
, ROW_NUMBER() OVER(ORDER BY code2) AS rn
FROM FULLT
WHERE code1 IS NULL
)
最后查询:
SELECT code1
, code2
FROM INNERT
UNION ALL
SELECT code1
, code2
FROM LEFTT
JOIN RIGHTT
ON LEFTT.rn = RIGHTT.rn
ORDER BY code1
, code2
初始数据:
; WITH
T1 (CODE) AS
( SELECT 'AAA' CODE UNION
SELECT 'BBB' UNION
SELECT 'CCC'
)
, T2 (CODE) AS
( SELECT 'BBB' CODE UNION
SELECT 'CCC' UNION
SELECT 'DDD'
)
帮助表:
, FULLT (code1, code2) AS
( SELECT T1.CODE AS code1
, T2.CODE AS code2
FROM T1
FULL OUTER JOIN T2
ON T1.CODE = T2.CODE
)
, INNERT (code1, code2) AS
( SELECT code1
, code2
FROM FULLT
WHERE code1 = code2
)
, LEFTT (code1, rn) AS
( SELECT code1
, ROW_NUMBER() OVER(ORDER BY code1) AS rn
FROM FULLT
WHERE code2 IS NULL
)
, RIGHTT (code2, rn) AS
( SELECT code2
, ROW_NUMBER() OVER(ORDER BY code2) AS rn
FROM FULLT
WHERE code1 IS NULL
)
最后查询:
SELECT code1
, code2
FROM INNERT
UNION ALL
SELECT code1
, code2
FROM LEFTT
JOIN RIGHTT
ON LEFTT.rn = RIGHTT.rn
ORDER BY code1
, code2
您的第二个子查询是否应该针对表2而不是表1?抱歉,当然可以。我更正了操作。@SSITRA:这两个字段
code
是否具有唯一约束?您的第二个子查询是否应该针对表2而不是表1?抱歉,当然可以。我更正了操作。@SSITRA:这两个字段code
是否具有唯一约束?