-1

我正在寻找一种方法来获取 3 个表之间的差异。我不能做的主要任务是比较表 a 的列并取决于它包含的内容,它与 2 列上的表 b 和 c 进行比较。一个例子将阐明我正在尝试做的事情:

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

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

#编辑1:

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

提前致谢

4

2 回答 2

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小提琴

编辑: 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不会被我的原始查询正确连接,但它应该在更新的查询中得到修复。

于 2013-06-06T21:08:07.457 回答
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 '%.%'),则查询会同时查找TableBTableC以查找HostName对应的位置IPAddressName匹配当前TableA行的IPAddressHostName。然后将两个表的结果组合起来,并返回联合集的一个值以替换当前行的HostName.

当当前行HostName确实有 a.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
;

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

于 2013-06-06T17:55:32.323 回答