2017-10-04 14 views
1

私はこのように見える2つのファイルを持っています。両方のファイルは1番目と2番目のフィールドでソートされます。AWK - 2つのファイルをキーと比較し、要約を印刷する(欠落、同じ、異なる)

ファイル

3337312|6dc1d4397108002245c770fa66ee4d7767dcc23e|1 
3337313|cb1c00eeccb25ea5a069da63a1b0c2565379ff9c|1 
3337318|61a813730578c552b62de5618e1d66b1eb74b4f8|1 
3337319|6af3b98f25a6a9b9d887486aefddfb53947bbf1c|1 
3337320|1e3126f41f848509efad0b3415b003704377778c|1 

ファイルB

3337312|6dc1d4397108002245c770fa66ee4d7767dcc23e|1 
3337315|780055f13efffcb4bee115c6cf546af85ac6c0a7|1 
3337316|19535297b9913b6bca1796b68505498d5e81b5ed|1 
3337318|61a813730578c552b62de5618e1d66b1eb74b4f8|1 
3337319|6af3b98f25a6a9b9d887486aefddfb53947bbf1c|1 

最初の行がキーである(ID用の複数の行が存在し得ます)。 3つのフィールド、パイプを区切ります。ファイルは約1GBです。私がやりたいのは何
は次のようになり、結果セットを取り戻すされています。ここではそれを実現するSQLコードです

3333 rows in File A 
4444 rows in File B 
1234 rows are identical 
2345 rows are different (aka the 2nd/3rd field are different but the key matches) 
111 rows in File A not in File B 
222 rows in File B not in File A 

、それは私のフォールバックです。

--CREATE TABLE aws_hash_compare (the_filename VARCHAR(100) NOT NULL, switch_id BIGINT, hash_value CHAR(40),the_count TINYINT) 

--CREATE UNIQUE CLUSTERED INDEX ucidx__awshashcompare__the_filename__switch_id ON aws_hash_compare(the_filename, switch_id) 

DECLARE @mSsql_filename sysname = 'FileA' 
DECLARE @mYsql_filename sysname = 'FileB' 


SELECT COUNT(*) AS MSSQL FROM aws_hash_compare 
WHERE the_filename = @mSsql_filename 

SELECT COUNT(*) AS MYSQL FROM aws_hash_compare 
WHERE the_filename = @mYsql_filename 


SELECT COUNT(*) AS switch_id_match FROM aws_hash_compare mysql 
INNER JOIN aws_hash_compare mssql 
ON mysql.the_filename = @mYsql_filename 
AND mssql.the_filename = @mSsql_filename 
AND mysql.switch_id = mssql.switch_id 

SELECT COUNT(*) AS complete_match FROM aws_hash_compare mysql 
INNER JOIN aws_hash_compare mssql 
ON mysql.the_filename = @mYsql_filename 
AND mssql.the_filename = @mSsql_filename 
AND mysql.switch_id = mssql.switch_id 
AND mssql.hash_value = mysql.hash_value 
AND mssql.the_count = mysql.the_count 

SELECT COUNT(*) AS hash_differences FROM aws_hash_compare mysql 
INNER JOIN aws_hash_compare mssql 
ON mysql.the_filename = @mYsql_filename 
AND mssql.the_filename = @mSsql_filename 
AND mysql.switch_id = mssql.switch_id 
AND (mssql.hash_value <> mysql.hash_value OR mssql.the_count <> mysql.the_count) 

SELECT COUNT(*) AS missing_from_MSSQL FROM aws_hash_compare mysql WHERE the_filename = @mYsql_filename 
AND NOT EXISTS (SELECT 1 FROM aws_hash_compare mssql WHERE the_filename = @mSsql_filename 
       AND mssql.switch_id = mysql.switch_id) 

SELECT COUNT(*) AS missing_from_MYSQL FROM aws_hash_compare mssql WHERE the_filename = @mSsql_filename 
AND NOT EXISTS (SELECT 1 FROM aws_hash_compare mysql WHERE the_filename = @mYsql_filename 
       AND mssql.switch_id = mysql.switch_id) 

答えて

2

次のawkは同じように役立ちます。

awk -F"|" ' 
FNR==NR{ 
    a[$0]=$0; 
    b[$1]; 
    next 
} 
FNR==1{ 
    file1_count=(NR-1) " rows in " ARGV[1] 
} 
($1 in b) && !($0 in a){ 
    first_field_matching++ 
} 
($0 in a){ 
    common++; 
    delete a[$0]; 
    next 
} 
{ 
    found_in_B_not_in_A++ 
} 
END{ 
    found_in_A_not_in_B=length(a); 
    print file1_count RS FNR " rows in " ARGV[2] RS common " rows are identical" \ 
RS first_field_matching " rows are different (aka the 2nd/3rd field are\ 
different but the key matches)" RS found_in_A_not_in_B " rows in File A\ 
not in File B" RS found_in_B_not_in_A " rows in File B not in File A" 
} 
' file_A file_B 

のは、以下ましょうファイルAとファイルB(私は$ 1は他の人と同じではありませんつの条件を確認するためにあなたの提供INPUT_FILESにマイナーチェンジを行っている)です。

cat file_A 
3337312|6dc1d4397108002245c770fa66ee4d7767dcc23e|1 
3337313|cb1c00eeccb25ea5a069da63a1b0c2565379ff9c|1 
3337318|61a813730578c552b62de5618e1d66b1eb74b4f8|1 
3337319|786af3b98f25a6a9b9d887486aefddfb53947bbf1c|1 
3337320|1e3126f41f848509efad0b3415b003704377778c|1 

cat file_B 
3337312|6dc1d4397108002245c770fa66ee4d7767dcc23e|1 
3337315|780055f13efffcb4bee115c6cf546af85ac6c0a7|1 
3337316|19535297b9913b6bca1796b68505498d5e81b5ed|1 
3337318|61a813730578c552b62de5618e1d66b1eb74b4f8|1 
3337319|6af3b98f25a6a9b9d887486aefddfb53947bbf1c|1 

上記のコードを実行すると、次の出力が同じになります。

5 rows in file_A 
5 rows in file_B 
2 rows are identical 
1 rows are different (aka the 2nd/3rd field aredifferent but the key matches) 
3 rows in File Anot in File B 
3 rows in File B not in File A 
+1

正確に何が必要なのですか。とても感謝しています! – mbourgon

+4

@mbourgon、これは1GBのファイルでどれくらいの時間がかかり、消費されるメモリ量が不思議です。もしできれば、私に知らせてください。 –

+2

そして速度比較対SQL – dawg

1

commを使用してファイルを比較し、awkを使用して結果を生成するバージョンです。それは遅くなるかもしれませんが、より少ないメモリを使用するかもしれません。 commでは、入力ファイルをソートする必要があります。

私は、キーがファイルごとに一度正確に表示されると仮定しています。

comm filea fileb | awk -F'\t' ' 
    BEGIN { na = nb = identical = common = 0 } 
    $1 { 
     split($1, f, /[|]/) 
     if (f[1] in b) {common++; delete b[f[1]]} else {a[f[1]]} 
     na++ 
    } 
    $2 { 
     split($2, f, /[|]/) 
     if (f[1] in a) {common++; delete a[f[1]]} else {b[f[1]]} 
     nb++ 
    } 
    $3 { 
     identical++ 
     na++ 
     nb++ 
    } 
    END { 
     printf "%d rows in file A\n", na 
     printf "%d rows in file B\n", nb 
     printf "%d rows are identical\n", identical 
     printf "%d rows are different but share a key\n", common 
     printf "%d rows in file A only\n", length(a) 
     printf "%d rows in file B only\n", length(b) 
    } 
' 
+1

テストの1つでそれを実行し、SQLと他のawkスクリプト(Sweet!)と同じ結果を得ました。しかし、ファイル内にキーのインスタンスが複数ある場合があります。同じswitch_idを持つ異なる行に対して複数のハッシュがある場合は、カウント(3番目のフィールド)を含める理由です。私は現在、誰かが "完全な"ファイルを比較するのを待っています。私がそれらを得ると、私は両方のバージョンを実行するために時間とメモリを共有します。再度、感謝します! – mbourgon

関連する問題