2013-06-05 98 views
-1

我正在寻找一种方法来获得3个表之间的差异。我不能做的主要任务是比较一个列表形式的表,并取决于它包含什么,它与2列的表b和c相比较。 一个例子阐明我想要做的事:比较一列与其他2列

Table A: 
IpAddress |HostName 
10.10.01.10 | somethingtada 
255.255.255.1| something.else 

Table B: 
IpAddress |HostName   |Name 
10.10.01.10 |somethingtada.tada |somethingtada 

Table C: 
IpAddress |HostName  |Name 
255.255.255.1| something.else |something 
1.1.1.1  | blabla.tada |tada 

,我需要有一个表,显示我这样

IpAddress |HostName   |TableA|TableB|TableC 
10.10.01.10 |somethingtada.tada|1  |1  |0 
255.255.255.1|something.else |1  |0  |1 
1.1.1.1  |blabla.tada  |0  |0  |1 

数据,因此如果不够清楚,当我有一个 ”。”在TableA的hostName列中(这种情况总是发生在tableA中),我将它与Hostname和其他表进行比较。但如果没有“。”在TableA的Hostname中,我将它与其他2个表的列名进行比较。

我有什么,现在是这样的:“”

select IPAddress, HostName, 
SUM(case when tbl = 'a' then 1 else 0 end) TableB, 
SUM(case when tbl = 'b' then 1 else 0 end) TableC, 
SUM(case when tbl = 'c' then 1 else 0 end) TableA 
from 
(
    select IPAdress, HostName,'a' tbl 
    from TableB 
    union all 
    select IPAdress, HostName,'b' tbl 
    from TableC 
    union all 
    select IPAdress, HostName,'c' tbl 
    from TableA 
) d 
group by IPAddress, HostName 

它运作良好,但我不知道如何对别人比对表取决于是否有一个在TableA的主机名列中。

#EDIT1:

Table A: 
IpAddress |HostName 
10.10.01.10 | somethingtada 
255.255.255.1| something.else 
255.10.10.1 | bliblio 
1.1.1.1  | tada 
2.2.2.2  | tada3.tada 
2.2.2.2  | tada5.tada 

Table B: 
IpAddress |HostName   |Name 
10.10.01.10 |somethingtada.tada |somethingtada 
255.1.1.1 |test3.test   |test3 
126.126.126.1|test4.test   |test4 
2.2.2.2  |tada5.tada   |tada5 

Table C: 
IpAddress |HostName  |Name 
255.255.255.1| something.else |something 
1.1.1.1  | blabla.tada |blabla 
255.1.1.1 | test3.test  |test3 
3.3.3.3  | test5.test  |test5 

,我需要有一个表,显示我这样

IpAddress |HostName   |TableA|TableB|TableC 
10.10.01.10 |somethingtada.tada|1  |1  |0 
255.255.255.1|something.else |1  |0  |1 
1.1.1.1  |blabla.tada  |1  |0  |1 
255.10.10.1 |blibio   |1  |0  |0 
255.1.1.1 |test3.test  |0  |1  |1 
126.126.126.1|test4.test  |0  |1  |0 
2.2.2.2  |tada3.tada  |1  |0  |0 
3.3.3.3  |test5.test  |0  |0  |1 
2.2.2.2  |tada5.tada  |1  |1  |0 

由于数据提前

+0

如果'A.HostName'与其他两个表中的'HostName'和'Name'都不匹配,会发生什么?输出应该是什么? –

+0

我们将看到IpAddress和HostName的数据,在TableB和TableC下我们将有一个“0”,并在表A下我们将有“1” – JoSav

+0

为了澄清,我的意思是当'A.IPAddress'匹配无论是“B.IPAddress”还是“C.IPAddress”,但相应的“A.HostName”都不匹配。因此,如果你所说的话仍然存在,输出将包含该IP地址的多个条目,其中一个使用“TableA = 1”和“TableB = TableC = 0”,其他使用“TableA = 0”并且“TableB = 1”或“TableC = 1”(或两者)。那是对的吗? –

回答

1

你可以尝试更换这部分:

select AdresseIP, HostName,'c' tbl 
from TableA 

像这样的东西:

SELECT 
    IPAddress, 
    COALESCE(
    CASE WHEN HostName NOT LIKE '%.%' THEN 
     (
     SELECT TOP 1 HostName 
     FROM (
      SELECT HostName 
      FROM TableB 
      WHERE IPAddress = TableA.IPAdress 
      AND Name = TableA.HostName 
      UNION ALL 
      SELECT HostName 
      FROM TableC 
      WHERE IPAddress = TableA.IPAdress 
      AND Name = TableA.HostName 
     ) s 
    ) 
    END, 
    HostName 
) AS HostName, 
    'c' AS tbl 
FROM TableA 

它的工作原理是这样的。对于TableA每一行,如果HostName没有.在它(NOT LIKE '%.%'),查询查找为HostNameTableBTableC,其中相应的IPAddressName匹配当前TableA行的IPAddressHostName。然后合并两个表格的结果,并返回统一集合的一个值以替代当前行的HostName

当前行的HostName本身是用来代替上面时,它确实有一个.或者如果没有相匹配的其他两个表中HostName被发现。

为了澄清,这是整个查询将如何取代我在开头提到的部分后想:

select IPAddress, HostName, 
SUM(case when tbl = 'a' then 1 else 0 end) TableB, 
SUM(case when tbl = 'b' then 1 else 0 end) TableC, 
SUM(case when tbl = 'c' then 1 else 0 end) TableA 
from 
(
    select AdresseIP, HostName,'a' tbl 
    from TableB 
    union all 
    select AdresseIP, HostName,'b' tbl 
    from TableC 
    union all 
    SELECT IPAddress, COALESCE( CASE WHEN HostName NOT LIKE '%.%' THEN ( SELECT TOP 1 HostName FROM ( SELECT HostName FROM TableB WHERE IPAddress = TableA.IPAdress AND Name = TableA.HostName UNION ALL SELECT HostName FROM TableC WHERE IPAddress = TableA.IPAdress AND Name = TableA.HostName ) s ) END, HostName ) AS HostName, 'c' AS tbl FROM TableA 
) d 
group by IPAddress, HostName 
;

请不要把你对性能气息。但是,也许这会给你一些想法,你最终会找到一个更好的解决方案。

+0

我忘了提及它,我很抱歉。我使用Sql server精简版(.sdf)它是我的应用程序的本地数据库 – JoSav

+0

当我尝试测试您的解决方案时,出现如下错误:解析查询时出现错误[令牌行号= 18,令牌行偏移量= 13,Token in error = SELECT]“。我会替换Top(1)*的”Top 1“,并且仍然有错误 – JoSav

+0

我忘了在'TOP 1'之后放置'HostName'。 –

2

这个怎么样

select 
    coalesce(a.ipaddress, b.ipaddress, c.ipaddress), 
    coalesce(b.hostname, c.hostname, a.hostname), 
    case when a.ipaddress is not null then 1 else 0 end, 
    case when b.ipaddress is not null then 1 else 0 end, 
    case when c.ipaddress is not null then 1 else 0 end 
from 
    tablea a 
    full join tableb b on 
    a.ipaddress = b.ipaddress and (
     (a.hostname like '%.%' and a.hostname = b.hostname) or 
     (a.hostname not like '%.%' and a.hostname = b.name) 
    ) 
    full join tablec c on 
    a.ipaddress = c.ipaddress and (
     (a.hostname like '%.%' and a.hostname = c.hostname) or 
     (a.hostname not like '%.%' and a.hostname = c.name) 
    ) 

SQL fiddle

编辑:舍甫琴科M的改进建议听起来不错。下面是完整的改进版本:

select 
    coalesce(a.ipaddress, b.ipaddress, c.ipaddress), 
    coalesce(b.hostname, c.hostname, a.hostname), 
    case when a.ipaddress is not null then 1 else 0 end, 
    case when b.ipaddress is not null then 1 else 0 end, 
    case when c.ipaddress is not null then 1 else 0 end 
from 
    tablea a 
    full join tableb b on 
    a.ipaddress = b.ipaddress and (
     (a.hostname like '%.%' and a.hostname = b.hostname) or 
     (a.hostname not like '%.%' and a.hostname = b.name) 
    ) 
    full join tablec c on 
    coalesce(a.ipaddress, b.ipaddress) = c.ipaddress and (
     (a.hostname like '%.%' and a.hostname = c.hostname) or 
     (a.hostname not like '%.%' and a.hostname = c.name) or 
     (a.hostname is null and b.hostname = c.hostname) 
    ) 

我没有时间去更新sqlfiddle和测试,但你应该能够看到一个区别,如果你在更大的输入运行它。 TableA=0 TableB=1 TableC=1的输出行将无法通过我的原始查询正确加入,但它应该在更新的查询中修复。

+0

完整连接可能会起作用。然而,'tablec'上的连接条件可能应该扩展为包含'tableb'。特别是,IP地址比较应该是'coalesce(a.ipaddress,b.ipaddress)= c.ipaddress'类型,并且需要有第三个分离成员,沿着'...或(a .hostname为null,b.hostname = c.hostname)...'。 –

+0

@AndriyM你的改进看起来不错,我已经更新了ansswer –