2016-04-30 16 views
3

同僚がデータをマッピングするために必要なテーブルをまとめ、テーブルはOP_IDとBillTypeの2つのフィールドで構成されています。理論的には、2つの間に1対1の対応が必要です。すべてのOp_IDには1つの請求タイプしかない必要があります。Count()はSQLで期待通りに機能しません

しかし、私がそれを使い始めたとき、異なるBillTypeを持つOP_IDが重複していることがわかりました。例えば:十分

SELECT OP_ID, BillType 
FROM MappingTable 
GROUP BY OP_ID, BillType 

シンプル:

OP_Id    BillType 
007a000v9GWkAAM BillReady 
007a000v9GWkAAM RateReady 

だから最初に私はIDとBillTypesのユニークな組み合わせにグループにデータをクエリを構築しました。このセットには、上記の2つのレコードが含まれていなければなりません。次に、集約されたデータセット内のOP_Idsをカウントするために、これを中心に別のクエリをラップしました。理論的には、複数のBillTypeを持つOP_IDは2回発生するので、1を超える数を返す必要があります。

SELECT OP_ID, BillType, Count(OP_ID) 
FROM 
    (
    SELECT OP_ID, BillType 
    FROM MappingTable 
    GROUP BY OP_ID, BillType 
    ) Base 
GROUP BY OP_ID, BillType 
HAVING Count(OP_ID) > 1 

しかし、このクエリは何も返しません。ここでは何でももっと不可解:

OP_ID   BillType CountOfOP_IDs 
007a000v9GWkAAM BillReady 1 
007a000v9GWkAAM RateReady 1 

だから明確にするための2つのレコードがあります。私はすでにそれは私が得るものだだまされやすい人、知っているので、私は、HAVING句を削除し、上記のみOP_IDを引っ張ってクエリを制限する場合OP_ID 007a000v9GWkAAMですが、SQLは1つしかカウントされません!

これはとても簡単なので、私はCOUNT()がどのように機能するかに関する基本的なものが不足していると確信しています。参考までに、私はSQL Server 2014で作業しており、両方の列はnvarcharです。私は、SQLが両方のレコードのOP_IDを同一であると評価することも確認しました。誰がなぜこれが起こっているのか知っていますか?

答えて

4

Countは、1つにグループ化された行の数をカウントします。外側のグループから請求書タイプを削除するだけです。

また、count distinctオプションも見てください。それはもっと簡単かもしれません。

1

あなたのアプローチは理にかなっています。私の推測では、OP_IDの値は微妙に異なります - おそらくエンコードの問題や文字の見た目の違いによるものでしょう。

これは簡単に見つかります。このクエリは何を返しますか?あなたはBillType値は、その後SELECTGROUP_CONCAT(BillType)を追加表示したい場合は

SELECT OP_ID 
FROM MappingTable 
GROUP BY OP_ID 
HAVING MIN(BillType) <> MAX(BillType); 

select mt.* 
from mappingtable 
where op_id = '007a000v9GWkAAM'; 

ところで、あなたはにクエリを簡素化することができます。

EDIT:

上記はすべて正しいのですが、外側のクエリはOP_IDBILL_TYPEによってグループ化されているので、あなたのクエリは動作しません。

SELECT OP_ID, Count(OP_ID) 
FROM (SELECT OP_ID, BillType 
     FROM MappingTable 
     GROUP BY OP_ID, BillType 
    ) Base 
GROUP BY OP_ID 
HAVING Count(OP_ID) > 1; 

あなたは同じキーで2回グループ化しているため、行は返されません。サブクエリは重複を削除するので、外側のカウントは常に1になります。

+0

正解と思われるものに匿名ダウンワードがある理由はありますか? –

+0

ダウン投票者ではありませんが、私の推測では、「このクエリは何を返すのですか?答えで。 --- 'HAVING MIN(BillType)<> MAX(BillType) 'は、2つの行が存在する場合には' OP_ID'値を見つけられません.1つはヌル 'BillType'を持ち、もう1つは値を持ちます。 'BillType'が' NOT NULL'であれば問題ではないかもしれませんが、それは明記されていないので、あなたは現在何か証拠にないと仮定しています。 – Andreas

+0

@アンドレアス。 。 。非常にありそうもない。私の答えの質問は、OPの結果につながる可能性のあるデータ品質に関するものです。 'having'節に' min() 'と' max() 'を使うのは、' NULL'値がないと仮定して、お勧めのアプローチです。質問にはその列に 'NULL'値の提案はありません。誰かがこれらの理由でdownvoteを行っている場合は、本当に理由を説明する必要があります。 –

1
SELECT * 
FROM MappingTable 
WHERE OP_ID in (SELECT OP_ID 
       FROM (SELECT OP_ID, count(*) ct 
         FROM MappingTable 
         GROUP BY OP_ID) 
       WHERE ct > 1) 

BOTH列の重複はありません(OP_IDの予期しない重複はありません)。

3

声明

SELECT OP_ID, BillType 
FROM MappingTable 
GROUP BY OP_ID, BillType 

は何もしません、これらの二つのフィールドに新しいGROUP BYを追加し、あなたが今OP_IDBillTypeの明確な組み合わせを持っている場合

SELECT DISTINCT OP_ID, BillType 
FROM MappingTable 

を言うには長い道のりです。

SELECT ... 
FROM (SELECT DISTINCT OP_ID, BillType 
     FROM MappingTable 
    ) Base 
GROUP BY OP_ID, BillType 
HAVING Count(OP_ID) > 1 

新しい「グループ」は、すべての内部SELECTから1行で構成されますので、COUNTは常にCount(OP_ID) > 1が常に偽であることを意味し、1になり、あなたは何も返さないでしょう。


はおそらく、あなたは複数の値を持つBillTypeOP_Id値を見つけるためのもの。その場合は、をGROUP BYから、suggested by @DonKirkbyとしてください。

あなたがそのに興味があるなら(少なくとも、研究したときにしばしば良い)あなたは、また、最初と最後のBillType値を取得することにより、2つの例の結果では、これらのBillType値のを得ることができます。

SELECT OP_ID, COUNT(*), MIN(BillType), MAX(BillType) 
FROM (SELECT DISTINCT OP_ID, BillType 
     FROM MappingTable 
    ) Base 
GROUP BY OP_ID 
HAVING COUNT(*) > 1 

またsuggested by @DonKirkbyとして、COUNT(DISTINCT ...)を使用して文全体を短縮することができます。

SELECT OP_ID, COUNT(DISTINCT BillType), MIN(BillType), MAX(BillType) 
FROM MappingTable 
GROUP BY OP_ID 
HAVING COUNT(DISTINCT BillType) > 1 
関連する問題