2015-03-09 3 views
1

У меня есть таблица с userIds и категориями продуктов prod. Я хочу получить таблицу уникальных userIds и связанных с ней самых популярных категорий продуктов prod. Другими словами, я хочу знать, какие категории товаров каждый клиент покупает больше всего. Как я могу достичь этого в PL/SQL или Oracle SQL?SQL получает наиболее часто встречающееся значение для каждого идентификатора пользователя

|userId|prod| 
|------|----| 
|123544|cars| 
|123544|cars| 
|123544|dogs| 
|123544|cats| 
|987689|bats| 
|987689|cats| 

Я уже видел SO вопросы для получения наиболее часто встречающееся значение столбца, но как я могу получить наиболее общее значение для каждого уникального userId?

+1

Это обязательный plsql? может быть sql? – Aramillo

+2

Как вы можете обращаться с галсами? Например: в ваших данных образца, Userid 987689 .. вы хотите летучих мышей или кошек? оба они наиболее встречаются (т.е. один раз). – Ditto

+0

Почему, по-вашему, вам нужна хранимая процедура? –

ответ

0
SELECT user_id, prod, prod_cnt FROM (
    SELECT user_id, prod, prod_cnt, RANK() OVER (PARTITION BY user_id ORDER BY prod_cnt DESC) AS rn 
     FROM (
     SELECT user_id, prod, COUNT(*) AS prod_cnt 
      FROM mytable 
      GROUP BY user_id, prod 
    ) 
) WHERE rn = 1; 

в сокровенной подзапроса я получаю COUNT каждого продукта пользователем. Затем я ранжировать их, используя аналитические (окно) функция RANK(). Тогда я просто выбрать все из тех, где RANK равно 1. Используя RANK() inst ead от ROW_NUMBER() гарантирует, что связи будут возвращены.

2

Вы должны использовать только SQL, чтобы решить эту проблему .. если вам действительно нужно это в PL/SQL, просто врезать этот запрос в пределах PLSQL ..

(установка)

drop table yourtable; 
    create table yourtable (
    userID number, 
    prod  varchar2(10) 
    ) 
/

    insert into yourtable values (123544, 'cars'); 
    insert into yourtable values (123544, 'cars'); 
    insert into yourtable values (123544, 'dogs'); 
    insert into yourtable values (123544, 'cats'); 
    insert into yourtable values (987689, 'bats'); 
    insert into yourtable values (987689, 'cats'); 

    commit; 

- - если связи не нарушены, эта логика возвращает как связи

with w_grp as (
     select userID, prod, count(*) over (partition by userID, prod) rgrp 
      from yourtable 
     ), 
    w_rnk as (
     select userID, prod, rgrp, 
       rank() over (partition by userID order by rgrp desc) rnk, 
      from w_grp 
     ) 
    select distinct userID, prod 
    from w_rnk 
    where rnk = 1 
/

     USERID PROD 
    ---------- ---------- 
     987689 bats 
     987689 cats 
     123544 cars 

- при условии, что вам просто нужно 1 .. это вернет 1 случайное, если они связаны. (т.е. на этот раз он вытащил 987689 летучих мышей, в следующий раз он может тянуть 987689 кошек. Он всегда будет возвращать 123544 автомобили, однако, так как нет галстука для того.

with w_grp as (
     select userID, prod, count(*) over (partition by userID, prod) rgrp 
      from yourtable 
     ), 
    w_rnk as (
     select userID, prod, rgrp, 
       row_number() over (partition by userID order by rgrp desc) rnum 
      from w_grp 
     ) 
    select userID, prod, rnum 
    from w_rnk 
    where rnum = 1 
/

     USERID PROD    RNUM 
    ---------- ---------- ---------- 
     123544 cars    1 
     987689 bats    1 

[править] Подчищены неиспользуемый разряд/row_number от функций, чтобы избежать путаницы [/ редактировать]

+0

Просто интересно, разве вы не можете избавиться от 'DISTINCT' в коде? И зачем вычислять row_number(), когда вы его не используете. – ruudvan

+0

Я использовал тот же запрос для обоих;) (т. Е. Делал оба в одном запросе .. так что да, если вы используете опцию RANK, удалите row_number, если вы используете опцию номера строки, удалите ранг. Что касается DISTINCT .. попробуйте удалить его ... RANK вытащит дубликаты для 123544 автомобилей - так как есть 2 строки, как с count (2) .. (так работает аналитика). Таким образом, чтобы получить желаемые результаты, вам нужно всего лишь 1 из эти строки не оба (то есть разные) – Ditto

+0

вы правы. Когда я вводил свой ответ, я использовал группу в первом запросе. Избавьтесь от дубликатов прямо там :) – ruudvan

Смежные вопросы