2016-10-03 102 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