我必须维护一个设计非常糟糕的可怕遗留数据库。所有表都有超过100列 - 一个有650列。数据库非常非规范化,我发现通常在同一行的几列中表示相同的数据。
例如,以下是其中一个表的列示例:
[MEMBERADDRESS] [varchar](331) NULL,
[DISPLAYADDRESS] [varchar](max) NULL,
[MEMBERINLINEADDRESS] [varchar](max) NULL,
[DISPLAYINLINEADDRESS] [varchar](250) NULL,
[__HISTISDN] [varchar](25) NULL,
[HISTISDN] [varchar](25) NULL,
[MYDIRECTISDN] [varchar](25) NULL,
[MYISDN] [varchar](25) NULL,
[__HISTALT_PHONE] [varchar](25) NULL,
[HISTALT_PHONE] [varchar](25) NULL,
事实证明,MEMBERADDRESS
和DISPLAYADDRESS
对于表中的所有行具有相同的值。我在这里展示的其他领域也是如此。
手动识别所有这类情况将非常困难和耗时。是否可以创建一个查询来确定两个字段在表中的每一行中是否具有相同的值?
如果没有,是否有任何现有工具可以帮助我识别这些问题?
答案 0 :(得分:2)
我看到有两种方法可以简化此查询:
以下是第二种方法的快速说明:
SELECT id, name, val FROM (
SELECT id, MEMBERADDRESS as val,'MEMBERADDRESS' as name FROM MyTable
UNION ALL
SELECT id, DISPLAYADDRESS as val,'DISPLAYADDRESS' as name FROM MyTable
UNION ALL
SELECT id, MEMBERINLINEADDRESS as val,'MEMBERINLINEADDRESS' as name FROM MyTable
UNION ALL
...
) first
JOIN (
SELECT id, MEMBERADDRESS as val,'MEMBERADDRESS' as name FROM MyTable
UNION ALL
SELECT id, DISPLAYADDRESS as val,'DISPLAYADDRESS' as name FROM MyTable
UNION ALL
SELECT id, MEMBERINLINEADDRESS as val,'MEMBERINLINEADDRESS' as name FROM MyTable
UNION ALL
...
) second ON first.id=second.id AND first.value=second.value
100列的手动工作很多(至少它没有增长为N^2
,就像第一种方法一样,但它仍然是很多手动输入)。使用小脚本生成与UNION ALL
连接的选项可能会更好。
答案 1 :(得分:1)
以下方法使用unpivot
创建三元组。它做了一些假设:值不为空;每一行都有一个id;和列具有兼容的类型。
select t.which, t2.which
from (select id, which, value
from MEMBERADDRESS
unpivot (value for which in (<list of columns here>)) up
) t full outer join
(select id, which, value
from MEMBERADDRESS
unpivot (value for which in (<list of columns here>)) up
) t2
on t.id = t2.id and t.which <> t2.which
group by t.which, t2.which
having sum(case when t.value = t2.value then 1 else 0 end) = count(*)
它的工作原理是创建一个包含三列的新表:id,列,以及列中的值。然后它在id上进行自连接(以便在一行内保持比较)和值(以获得匹配值)。此自连接应始终匹配,因为查询的两半中的列相同。
having
然后计算给定列对的两侧相同值的数量。如果所有这些都相同,则匹配成功。
您也可以省略having
子句并使用类似:
select t.which, t2.which, sum(case when t.value = t2.value then 1 else 0 end) as Nummatchs,
count(*) as NumRows
获取更完整的信息。