在sql server 2012中查找最常见的值

时间:2015-02-08 12:11:43

标签: sql sql-server sql-server-2012 pivot

我想找到每个客户购买的最常用的产品。我的数据集是这样的:

CustomerID     ProdID    FavouriteProduct
    1              A              ?
    1              A              ?
    1              A              ?
    1              B              ?
    1              A              ?
    1              A              ?
    1              A              ?
    1              B              ?
    2              A              ?
    2              AN             ?
    2              G              ?
    2              C              ?
    2              C              ?
    2              F              ?
    2              D              ?
    2              C              ?

产品太多了,所以我不能将它们放在数据透视表中。

答案看起来像这样:

CustomerID     ProdID    FavouriteProduct
    1              A              A
    1              A              A
    1              A              A
    1              B              A
    1              A              A
    1              A              A
    1              A              A
    1              B              A
    2              A              C
    2              AN             C
    2              G              C
    2              C              C
    2              C              C
    2              F              C
    2              D              C
    2              C              C

查询可能如下所示:

Update table
set FavouriteProduct = (Select 
                            CustomerID, Product, Max(Count(Product)) 
                        From Table 
                        group  by CustomerID, Product) FP    

5 个答案:

答案 0 :(得分:2)

获得最常用产品的另一种方法是使用row_number()

select customerid, productid,
       max(case when seqnum = 1 then productid end) over (partition by customerid) as favoriteproductid
from (select customerid, productid, count(*) as cnt,
             row_number() over (partition by customerid order by count(*) desc) as seqnum
      from customer c
      group by customerid, productid
     ) cp;

答案 1 :(得分:2)

要完全按照问题中的描述返回行,您可以尝试使用表格表达式(我在我的示例中使用CTE)首先返回流行度排名,其中数字越大,产品越受欢迎为每个客户。

WITH RankTable AS (
  SELECT
    CustomerID, ProductID, COUNT(*) AS Popularity
  FROM TableA
  GROUP BY CustomerID, ProductID
)

然后可以通过首先在原始表(TableA)和表表达式(RankTable)上执行内部联接,然后使用窗口函数在FavoriteProduct列中创建值来返回完整结果表。

SELECT 
    P.CustomerID
  , P.ProductID
  , FIRST_VALUE(P.ProductID) OVER(
      PARTITION BY R.CustomerID
      ORDER BY R.Popularity DESC, R.ProductID) AS FavoriteProduct
FROM TableA AS P
  INNER JOIN RankTable AS R
    ON P.CustomerID = R.CustomerID
    AND P.ProductID= R.ProductID;

答案 2 :(得分:1)

感谢尼克,我找到了找到最常见价值的方法。我与你分享它是如何运作的:

   Select CustomerID,ProductID,Count(*) as Number 
   from table A 
   group by CustomerID,ProductID 
   having Count(*)>= (Select Max(Number) from (Select CustomerID,ProductID,Count(*) as Number from table B where B.CustomerID= A.CustomerID  group by CustomerID,Product)C) 

答案 3 :(得分:1)

如果您的SQL执行速度不够快而且客户也在较小的表中,这可能会更好用::

select C.CustomerId, R.ProductID
from Customer C
outer apply (
  Select top 1 ProductID,Count(*) as Number 
  from table A 
  where A.CustomerId = C.CustomerId
  group by ProductId
  order by Number desc 
) R

答案 4 :(得分:1)

这一个,基于本页末尾的示例:http://www.sql-server-performance.com/2006/find-frequent-values/可能会更快:

SELECT CustomerID, ProdID, Cnt 
FROM 
(
    SELECT CustomerID, ProdID, COUNT(*) as Cnt, 
    RANK() OVER (
       PARTITION BY CustomerID
       ORDER BY COUNT(*) DESC
    ) AS Rnk 
    FROM YourTransactionTable
    GROUP BY CustomerID, ProdID
) x 
WHERE Rnk = 1

这个使用RANK()函数。在这种情况下,您不必加入同一个表(意味着需要的工作少得多)

现在要更新现有数据,我喜欢将我的数据集包装在WITH中,以使调试更容易,最后的更新更简单:

;WITH
(
  SELECT CustomerID, ProdID, Cnt 
  FROM 
  (
     SELECT CustomerID, ProdID, COUNT(*) as Cnt, 
     RANK() OVER (PARTITION BY CustomerID
     ORDER BY COUNT(*) DESC) AS Rnk 
     FROM TransactionTable
     GROUP BY CustomerID, ProdID
  ) x 
  WHERE Rnk = 1
) As SRC

 UPDATE FavouriteTable
 SET Favourite = SRC.ProdID
 FROM SRC
 WHERE SRC.CustomerID = Favourite.CustomerID