我正在尝试优化我的代码。下面描述的解决方案工作正常,但我很确定有更好的方法来做到这一点。你有什么建议吗?
我有一张包含商业合约和一些特征属性的表:
table_contracts
contract_number attribute_1 attribute_2 attribute_3
123 a e t
456 a f s
789 b g s
第二个表格将每个合同映射到特定的组。这些组具有不同的优先级(更高的数字=>更高的优先级)。如果属性列为空,则表示不需要(=> m3是catch all mapping)
table_mappings
map_number priority attribute_1 attribute_2 attribute_3
m1 5 a e t
m2 4 a
m3 3
因此,我需要contract_number和具有最高优先级的相应map_number。
我就是这样做的,它有效,但是有谁知道如何优化它?
with
first_selection as
(
select
table_contracts.contract_number
,table_mappings.priority
,row_number() over(partition by table_contracts.contract_number order by table_mappings.priority desc)
from table_contracts
left join table_mappings
on (table_contracts.attribute_1 = table_mappings.attribute_1 or table_mappings.attribute_1 is null)
and (table_contracts.attribute_2 = table_mappings.attribute_2 or table_mappings.attribute_2 is null)
and (table_contracts.attribute_3 = table_mappings.attribute_3 or table_mappings.attribute_3 is null)
),
second_selection as
(
select
table_contracts.contract_number
,table_mappings.priority
,table_mappings.map_number
from table_contracts
left join table_mappings
on (table_contracts.attribute_1 = table_mappings.attribute_1 or table_mappings.attribute_1 is null)
and (table_contracts.attribute_2 = table_mappings.attribute_2 or table_mappings.attribute_2 is null)
and (table_contracts.attribute_3 = table_mappings.attribute_3 or table_mappings.attribute_3 is null)
)
select
first_selection.contract_number
,second_selection.map_number
from first_selection
join second_selection
on first_selection.contract_number = second_selection.contract_number and first_selection.priority = second_selection.priority
where first_selection.rn = 1
此代码的输出为:
Results
contract_number map_number
123 m1
456 m2
789 m3
答案 0 :(得分:0)
我认为你只需要其中一个选择:
with prioritized as(
select c.contract_number, c.attribute_1, c.attribute_2, c.attribute_3, m.map_number
,row_number() over(
partition by c.contract_number
order by m.priority desc
) as rn
from table_contracts c
left join table_mappings m on(
(c.attribute_1 = m.attribute_1 or m.attribute_1 is null)
and (c.attribute_2 = m.attribute_2 or m.attribute_2 is null)
and (c.attribute_3 = m.attribute_3 or m.attribute_3 is null)
)
)
select *
from prioritized
where rn = 1
答案 1 :(得分:0)
使用与您类似的CTE版本尝试以下逻辑。希望它有所帮助!
WITH contracts AS
(SELECT 123 AS contract_number, 'a' AS attribute_1, 'e' AS attribute_2, 't' AS attribute_3 FROM dual
UNION
SELECT 456, 'a', 'f', 's' FROM dual
UNION SELECT 789, 'b', 'g', 's' FROM dual
),
mappings AS
(SELECT 'm1' AS map_number, 5 AS priority, 'a' AS attribute_1, 'e' AS attribute_2, 't' AS attribute_3 FROM dual
UNION
SELECT 'm2', 4, 'a', NULL, NULL FROM dual
UNION
SELECT 'm3', 3, NULL, NULL, NULL FROM dual
),
prioritymap AS
(SELECT contract_number,
map_number,
Rank() over(PARTITION BY contracts.contract_number ORDER BY mappings.priority DESC) AS rank
FROM contracts
JOIN mappings
ON ( contracts.attribute_1 = mappings.attribute_1 OR mappings.attribute_1 IS NULL )
AND ( contracts.attribute_2 = mappings.attribute_2 OR mappings.attribute_2 IS NULL )
AND ( contracts.attribute_3 = mappings.attribute_3 OR mappings.attribute_3 IS NULL )
)
SELECT contract_number, map_number
FROM prioritymap
WHERE prioritymap.rank = 1
答案 2 :(得分:0)
您可以在给定条件下简单地连接表(maping表中的属性为null或必须与contract表中的属性匹配)。然后按合同编号聚合以获得最佳map_number。
./configure
无论如何,您正在为所有合同执行此操作,并且映射可能与任何属性组合匹配,因此这将导致全表扫描。我能看到更快更快的唯一方法是并行执行。也许DBMS设置为自动执行此操作,否则您可以使用提示:
select
c.contract_number,
max(m.map_number) keep (dense_rank last order by m.priority) as map_number
from table_contracts c
join table_mappings m
on (m.attribute_1 is null or m.attribute_1 = c.attribute_1)
and (m.attribute_2 is null or m.attribute_2 = c.attribute_2)
and (m.attribute_3 is null or m.attribute_3 = c.attribute_3)
group by c.contract_number
order by c.contract_number;