2016-10-03 23 views
0

ネットを検索しましたが、私の問題の解決策が見つからないため、キーワードを正しく表現してはいけません。それは再帰かもしれないと思うが、私は確かではない。SQL Server 2012 - リトルガイダンス

私は、次のカテゴリを持つテーブルを持っている:

ID, Author, Customer, Group 

サンプルデータセットは次のように次のようになります。その可能性顧客はもっとそして1本の著者はそうチェックアウト1個の鉱石を有することができる

ID |  Author | Customer | Group 
------------------------------------------ 
    1 | Paula Hawkins | John Doe | NULL 
    2 | Harlan Coben | John Doe | NULL 
    3 | James Patterson| John Doe | NULL  
    4 | Paula Hawkins | Jane Doe | NULL  
    5 | James Patterson| Jane Doe | NULL 
    6 | James Patterson| Steven Doe| NULL  
    7 | Harlan Coben | Steven Doe| NULL 
    8 | Paula Hawkins | Harry Doe | NULL  
    9 | James Patterson| Harry Doe | NULL 

私がしようとしているのは、(顧客名に関係なく)チェックアウトされた総額に基づいて一意のIDでグループ化することです(顧客名に関係なく)。

ID |  Author | Customer | Group 
-------------------------------------------- 
    1 | Paula Hawkins | John Doe | 1  
    2 | Harlan Coben | John Doe | 1 
    3 | James Patterson| John Doe | 1 
    4 | Paula Hawkins | Jane Doe | 2  
    5 | James Patterson| Jane Doe | 2  
    6 | James Patterson| Steven Doe | 3  
    7 | Harlan Coben | Steven Doe | 3  
    8 | Paula Hawkins | Harry Doe | 2  
    9 | James Patterson| Harry Doe | 2 

最終的なグループカテゴリはその顧客のユニークな価値を表します(他の顧客は、チェックアウトしたものすべてが他のすべてのものと一致する場合のみ同じ価値を持ちます)顧客がチェックアウトした)。

上記のデータを使用すると、HarryとJaneは正確に同じ著者をチェックアウトしているので、同じグループに属しますが、JohnとStevenは異なる組み合わせを持ち、独自のグループを持っています。

これはうまくいけばうまくいきます。これは再帰と呼ばれるものですか?もしそうなら、私は一意のid値の何らかの並べ替えを使用するcteソリューションに目を向けるでしょう。あなたが助けてくれてありがとう。

+3

サンプルデータに基づいて、結果としてデータに見たいものを追加できますか?少なくとも私のために、あなたが実際にそこに見たいものはまだ不明です。 (私の無能を許してください) – Jens

+0

NULLの先頭のグループは前のもので、下のグループの値は後のものです。基本的に、それぞれの一意のグループを識別する値が設定されます。 – TStewartFan

答えて

0

正確なグループ順を取得する方法はわかりませんが、顧客をまとめてグループ化するには、作成者をFOR XMLと組み合わせて、完全一致に基づいて顧客をグループ化することができます。

WITH cte AS (
    SELECT 
     *, 
     RANK() OVER (ORDER BY Authors) [Group] 
    FROM ( 
     SELECT 
      [Customer], 
      STUFF((SELECT ',' + [Author] 
        FROM myTable WHERE Customer = mt.Customer 
        ORDER BY Author 
        FOR XML PATH('')), 1, 1, '') AS Authors 
     FROM 
      myTable mt 
     GROUP BY [Customer]) t 
) 

SELECT 
    mt.[ID], 
    mt.[Author], 
    mt.[Customer], 
    cte.[Group] 
FROM 
    cte 
    JOIN myTable mt ON mt.Customer = cte.Customer 
ORDER BY mt.[ID] 

SQL FIDDLE DEMO

+0

私はXMLソリューションを試したことはありませんでしたが、最初の結果に基づいてIDを136以上作成しましたが、私は約40のラインに沿って何かを期待していました。私の質問。ありがとう。 – TStewartFan

+0

あなたに戻って遅れて申し訳ありませんが、この数学教授が私を殺しています。私はこれを私の問題のために働かせることができました。なぜXMLを読んでその理由を理解する必要があります。方向性をありがとう、それは確かに正しい道を私を得た。 – TStewartFan

0

...カーソルが遅いですが、彼らも理解しやすくしているカーソルを使用してみてください。..

ここではサンプル実装です...

DECLARE @GroupExists Bit 
DECLARE @CurrGroup Int 
DECLARE @NextGroup Int 
DECLARE @Customer VARCHAR(250) 

SET @NextGroup = 1 

DECLARE customer_cursor CURSOR FAST_FORWARD 
FOR SELECT distinct Customer FROM dbo.TableName 

OPEN customer_cursor 
FETCH NEXT FROM customer_cursor 
INTO @Customer 

WHILE @@FETCH_STATUS = 0 
BEGIN 

    SET @GroupExists = 0 
    --Test condition to check if group of authors in in use 

    IF @GroupExists = 1 Then 
    BEGIN 
     UPDATE dbo.TableName 
     SET Group = @CurrGroup 
     WHERE Customer = @Customer 
    END 
    ELSE 
    BEGIN 
     UPDATE dbo.TableName 
     SET Group = @NextGroup 
     WHERE Customer = @Customer 

     SET @NextGroup= @NextGroup+ 1 
    END 

    FETCH NEXT FROM customer_cursor 
    INTO @Customer 
END 
0

標準SQLを使用してグループを生成できるはずです。次のクエリでジョブを実行する必要があります。私はそのパフォーマンスの約束をしない。

WITH 
CTE_CheckOutBookCount AS 
(
    SELECT [ID] 
      ,[Author] 
      ,[Customer] 
      ,COUNT([Author]) OVER (PARTITION BY [Customer]) AS [CheckOutBooks] -- Count the number of books checked out by each customer. This will be used for our initial compare between customers. 
    FROM CheckedOutBooks 
), 
CTE_AuthorAndCountCompare AS 
(
    SELECT   CB.[ID] 
        ,CBC.[Customer] AS MatchedCustomers 
    FROM   CTE_CheckOutBookCount CB 
    INNER JOIN CTE_CheckOutBookCount CBC ON CB.[Author] = CBC.[Author] AND CB.[CheckOutBooks] = CBC.[CheckOutBooks] --Join customer information on number of books checked out and author name of books checked out. 
) 
,CTE_MatchedCustomers 
AS 
(
    SELECT 
      [ID] 
      ,[Author] 
      ,[Customer] 
      --Get the minimum record id of customers which match exactly on count and authors checked out. This will be used to help generate group ID. 
      ,(
       SELECT MIN(ID) 
       FROM CTE_AuthorAndCountCompare 
       WHERE CheckedOutBooks.[Customer] = CTE_AuthorAndCountCompare.MatchedCustomers 
      ) MinID 
    FROM CheckedOutBooks 
) 
SELECT 
     [ID] 
     ,[Author] 
     ,[Customer] 
     ,DENSE_RANK() OVER (ORDER BY MinID) AS [Group] -- Generate new group id 
FROM CTE_MatchedCustomers 
ORDER BY ID