2017-04-21 2 views
0

私は以下のテーブルを持っています - テーブルには顧客キーとロールが設定されています。各顧客キーには複数の異なるロールが関連付けられていて、特定のロールのリストで顧客キーを識別できるようにしたいと考えています。たとえば、すべてのアカウントをロール(「A」、「B」、「C」)で識別できるようにしたいと考えています。Microsoft SQL Server 2014 - 自己結合によるデカルト結果を防ぐことはできません

+--------------+------------+----+ 
| customer_key | sales_role | | 
+--------------+------------+----+ 
|   123 | A   | | 
|   123 | B   | | 
|   123 | C   | | 
|   456 | A   | | 
|   456 | B   | | 
|   789 | A   | | 
|   789 | B   | | 
|   789 | C   | | 
|   987 | A   | | 
|   987 | B   | | 
|   987 | C   | | 
|   987 | D   | | 
|   654 | E   | | 
|   654 | F   | | 
|    | Te<br />st | 45 | 
+--------------+------------+----+ 

私は2つの役割までのアカウントを特定するには、以下のクエリを使用して成功を収めてきました:

SELECT 
c.customer_key 
,COUNT(c.sales_role) as 'count' 
FROM 
    table a 
    INNER JOIN table b ON a.customer_key=b.customer_key  
    RIGHT JOIN table c ON c.customer_key=a.customer_key 
WHERE 
    a.sales_role = 'A' AND 
    b.sales_role = 'B' 
GROUP BY c.customer_key 
HAVING 
    COUNT(c.sales_role) = 2 

上記のクエリは、「456」CUSTOMER_KEY私を与えるだろう。

しかし、私は次のクエリでより多くの役割を識別するために結合を追加しようとすると、私はデカルト製品を取得します。

SELECT 
e.customer_key 
,COUNT(e.sales_role) as 'count' 
FROM 
    table a 
    INNER JOIN table b ON a.customer_key=b.customer_key  
    INNER JOIN table c ON a.customer_key=c.customer_key 
    INNER JOIN table d ON a.customer_key=d.customer_key 
    RIGHT JOIN table e ON e.customer_key=a.customer_key 
WHERE 
    a.sales_role = 'A' 
    AND b.sales_role = 'B'  
    AND c.sales_role = 'C' 


GROUP BY e.customer_key 
HAVING 
    COUNT(e.sales_role) = 3 

私はここで何を試しても分かりませんが、どんな助けでも大歓迎です。

答えて

2

あなたが必要なものを行う必要があり、複数の接続を必要としないこのクエリで、:

SELECT 
a.customer_key 
,COUNT(DISTINCT a.sales_role) as 'count' 
FROM table a 
WHERE a.sales_role IN ('A', 'B') 
GROUP BY a.customer_key 
HAVING 
    COUNT(DISTINCT a.sales_role) = 2 

あなたは、A、B、およびCをチェックし、必要に応じてINとHAVINGステートメントを変更する必要があり

あなたが探している値のみを持つレコードを返す必要がある場合は、他のロールの存在をテストしてそれらを除外するクエリを変更する必要があります。これは次のように行うことができます。

SELECT 
    a.customer_key 
    ,COUNT(DISTINCT a.sales_role) as 'count' 
FROM table a 
WHERE a.sales_role IN ('A', 'B') 
AND NOT EXISTS (
    SELECT * 
    FROM table b 
    WHERE b.customer_key = a.customer_key 
    AND b.sales_role NOT IN ('A', 'B') 
    ) 
GROUP BY a.customer_key 
HAVING 
    COUNT(DISTINCT a.sales_role) = 2 
+0

ありがとう、これはトリックを行ったようです。クエリのNOT EXISTS部分について説明してもらえますか? – raidboss

+0

確かに。特定のcustomer_key値が探しているセールスロールと一致することを確認すると、NOT EXISTS内のクエリは、その顧客に割り当てられた他のセールスロールがあるかどうかを調べます。 NOT EXISTS()は、そのクエリに何も見つからなければTRUEを返し、そのクエリに一致する行があればFALSEを返します。 「この問合せで行が戻されない場合はTRUE、それ以外の場合はFALSEが戻されます」のように読み取ることができます。 –

+0

非常に徹底的な説明、ありがとう、もう一度:) – raidboss

0

あなたは試してみる、カウントするコンビネーションsale_rolesを数え、クエリの下に調整することができます。

SELECT Customer_Key 
    , SUM(CASE Sales_Role WHEN 'A' THEN 1 
         WHEN 'B' THEN 1 
         WHEN 'C' THEN 1 
          ELSE 0 END) CntABC 
    , SUM(CASE Sales_Role WHEN 'A' THEN 1 
         WHEN 'B' THEN 1    
          ELSE 0 END) CntAB 
    , SUM(CASE Sales_Role WHEN 'E' THEN 1 
      ELSE 0 END) CntE 
FROM table 
GROUP BY Customer_Key 
関連する問題