2013-03-25 84 views
1

我面临着返回前N对产品的问题,即客户购买的共同点。让说,我有以下查询:获得前N对产品,客户通常购买

SELECT c.CustomerKey, ProductAlternateKey 
FROM 
    [AdventureWorksDW2008R2].[dbo].[FactInternetSales] FIS JOIN 
    dbo.DimCustomer C ON C.CustomerKey = FIS.CustomerKey JOIN 
    dbo.DimProduct P ON P.ProductKey = FIS.ProductKey 

GROUP BY 
    C.CustomerKey, P.ProductAlternateKey 

,并返回结果如下:

CustomerKey | ProductAlternateKey| 
-------------+-----------+ 
0001   | A     | 
0001   | B     | 
0002   | A     | 
0002   | B     | 
0002   | C     | 
0003   | B     | 
0003   | C     | 
0004   | A     | 
0004   | B     | 
0005   | A     | 
0005   | C     | 

从这个查询我想找到顶部2对客户买,所以在我的例子产品 - >(A,B)出现3次,(B,C)→出现2次

+1

,并将答案在这种情况下怎么办? – 2013-03-25 16:23:39

+0

我在我的案例中添加了答案来编辑我的问题。 – Konza 2013-03-26 08:36:01

回答

1

这给测试:

declare @Orders table (OrderID int identity, PersonID int, Description varchar(32), ProductId int, Amount int); 

insert into @Orders values (1, 'Shirt', 1, 20),(1, 'Shoes', 2, 50),(2, 'Shirt', 1, 22),(2, 'Shoes', 2, 20),(3, 'Shirt', 1, 20),(3, 'Shoes', 2, 50),(3, 'Hat', 3, 20),(4, 'Shirt', 1, 20),(5, 'Shirt', 1, 20),(5, 'Pants', 4, 30),(6, 'Shirt', 1, 20),(6, 'RunningShoes', 5, 70),(6, 'Hat', 3, 20),(7, 'Shirt', 1, 22),(7, 'Shoes', 2, 40),(7, 'Coat', 6, 80); 

select 
    top 2  
    I.Description, 
    M.Description 
from @Orders as I 
inner join @Orders as C on C.ProductId = I.ProductId and C.PersonId <> I.PersonId 
inner join @Orders as M on C.PersonId = M.PersonId and C.ProductId <> M.ProductId 
where 
    I.productid = 3 
    and I.ProductId<>M.ProductId 
group by 
    I.Description 
    ,M.Description 
order 
    by count(2) desc 
+0

这是非常有用的,但我不确定它是否按预期工作。当我选择Top 3时,它会返回Shoes - Shirts和Shirts - Shoes as different pairs。 – Konza 2013-03-26 15:33:02

+0

我完全删除了顶部,并没有得到你所建议的 – 2013-03-26 19:25:40

+0

这是因为我删除了“productID = 3”的条件。是否有可能无需修复productID? – Konza 2013-03-28 10:36:13

1

使用RANK或DENSERANK函数。 MSDN上排名功能:http://msdn.microsoft.com/en-us/library/ms176102.aspx

用法示例与自我解压的SQL:

declare @Person Table (personID int identity, person varchar(8)); 

insert into @Person values ('Brett'),('Sean'),('Chad'),('Michael'),('Ray'),('Erik'),('Queyn'); 

declare @Orders table (OrderID int identity, PersonID int, Desciption varchar(32), Amount int); 

insert into @Orders values (1, 'Shirt', 20),(1, 'Shoes', 50),(2, 'Shirt', 22),(2, 'Shoes', 20),(3, 'Shirt', 20),(3, 'Shoes', 50),(3, 'Hat', 20),(4, 'Shirt', 20),(5, 'Shirt', 20),(5, 'Pants', 30), 
(6, 'Shirt', 20),(6, 'RunningShoes', 70),(7, 'Shirt', 22),(7, 'Shoes', 40),(7, 'Coat', 80); 

with a as 
    (
    Select 
     person 
    , o.Desciption 
    , o.Amount 
    , rank() over(partition by p.personId order by Amount) as Ranking 
    , Dense_rank() over(partition by p.personId order by Amount) as DenseRanking 
    from @Person p 
     join @Orders o on p.personID = o.PersonID 
    ) 
select * 
from a 
where Ranking <= 2 -- determine top 2, 3, etc.... whatever you want. 
order by person, amount 
+0

我认为这个查询将返回最常购买的产品,而不是一起购买的产品对。但也许我错了? – Konza 2013-03-26 09:05:45

+0

您可以更改窗口函数的'分区依据'部分以进一步削减它。例如,如果我有一个像红色或蓝色衬衫的“类型”订单。我可以完成(由p.personid分区,按金额分类)。从本质上来说,分组就是分区,而排序则是如何确定排名的首位或最后位置。当你想要中值或前n个值时;由于它们可以灵活地使用内联而不是强制分组子句,因此窗口化函数变得非常强大。我甚至可以做4到5个,因为我不需要分组,所以它很灵活。 – djangojazz 2013-03-26 15:31:50

相关问题