将列与其他2个不同的列进行比较

时间:2013-06-05 17:09:28

标签: sql sql-server-ce

我正在寻找一种方法来获得3个表之间的差异。我不能做的主要任务是比较列表格a并取决于它包含什么,它与表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的主机名中,我将它与另外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

它运作良好,但我不知道如何比较其他表取决于是否有“。”在表A中的主机名列中。

#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

提前致谢

2 个答案:

答案 0 :(得分: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

编辑: Andriy 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的输出行,但应在更新的查询中修复它。

答案 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 '%.%'),则查询会同时查找TableB和{{1}对于TableC,相应的HostNameIPAddress匹配当前Name行的TableAIPAddress。然后合并两个表的结果,并返回一个联合集的值,以替换当前行的HostName

如果当前行的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
;

请不要屏住表演。但是,也许这会给你一些想法,你最终会找到一个更好的解决方案。