2015-02-08 2 views
1

Я хочу найти наиболее часто используемый продукт, приобретенный каждым покупателем. мой набор данных, как это:Поиск наиболее частого значения в SQL Server 2012

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  
+0

Pivot не имеет ничего общего с этим. Сначала выполните запрос, который возвращает каждый избранный продукт. Ты почти там. Затем мы можем помочь с обновлением. –

+0

@ Nick.McDermaid - Я знаю, я только сказал, что если количество продуктов было три или четыре, мы могли бы легко найти любимый продукт через сводную таблицу. но сейчас? – Ariox66

+1

Перейти к началу страницы http://www.sql-server-performance.com/2006/find-frequent-values/ и посмотреть, можете ли вы адаптировать SQL для возврата списка всех клиентов с их любимым продуктом. –

ответ

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) 
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 
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

Это один, основанный на примере в конце этой страницы: 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 
2

для возврата строки точно так, как вы описали в этом вопросе, вы можете попробовать использовать табличное выражение (я использовал КТР в моем примере) для первого возвращения популярности рейтинга , где, чем выше число, тем популярнее продукт для каждого клиента.

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;