2016-10-03 96 views
0

我已經搜索了網絡,但我確定我不能正確地措詞我的關鍵字,因爲我沒有找到我的問題的可能解決方案。認爲這可能是遞歸,但我不太確定。SQL Server 2012 - 一點指導

我有有以下幾類表:

ID, Author, Customer, Group 

的樣本數據集將是這樣的:

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 

它很有可能同一個客戶可能被發現數百次用於多本書,所以最終的組別類別將代表該客戶的獨特價值(其他客戶只有在他們簽出的所有內容也匹配其他所有內容時才具有相同的價值客戶已經簽出)。

使用上述數據,哈利和珍擁有完全相同的作者簽出,因此他們在同一組中,但約翰和史蒂文有不同的組合,因此他們有自己的獨特組。

希望這是有道理的。這就是所謂的遞歸?如果是這樣,那麼我會看看一個cte解決方案,它使用某種排名的唯一id值。感謝您給予的任何幫助。

+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解決方案,但是基於最初的結果,它創建了136個組ID,但我期望沿着最多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