2013-06-05 137 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 –