Наибольшее появление значения в каждой группе - PullRequest
2 голосов
/ 21 января 2011

У меня есть таблица с идентификатором пользователя и идентификаторами веб-сайтов, по которым он просматривал. Таблица выглядит так:

| user-ID | website-ID |
|       1 |          1 |
|       1 |          2 |
|       1 |          1 |
|       1 |          4 |
|       2 |          1 |
|       2 |          2 |
|       2 |          5 |
|       2 |          2 |

Я бы хотел выбрать идентификатор веб-сайта, в котором каждый пользователь чаще всего участвовал. Как видите, min , max или avg здесь не будут работать. Есть идеи?

Ответы [ 4 ]

3 голосов
/ 21 января 2011

Я ввел временную таблицу, чтобы было легче читать. Вы можете, конечно, заменить этот запрос встроенным и при желании удалить временную таблицу.

Первый выбор суммирует посещения на пользователя и веб-сайт.

Второй выбор находит максимальное количество посещений для каждого пользователя в подзапросе, а затем присоединяется к временной таблице, чтобы найти веб-сайт, чье количество соответствует этому максимальному значению.

create temporary table TempSum
    select user-ID, website-ID, count(*) as TotalCount
        from YourTable
        group by user-ID, website-ID

select ts.user-ID, ts.website-ID, ts.TotalCount
    from (select user-ID, max(TotalCount) as MaxCount
              from TempSum
              group by user-ID) ms
        inner join TempSum ts
            on ts.user-ID = ms.user-ID
                and ts.TotalCount = ms.MaxCount
0 голосов
/ 22 января 2011

Работай, поштучно - шаг за шагом.

Обратите внимание, что показанные данные не имеют первичного ключа; Есть повторяющиеся строки. Предположительно, полный набор данных содержит другую информацию, такую ​​как время посещения, которая делает строки уникальными. Для рассматриваемого вопроса это не имеет большого значения, но вы стремитесь иметь таблицы с первичными ключами, когда это возможно (что, по сути, всегда).

Также обратите внимание, что идентификаторы 'user-ID' и 'website-ID' недопустимы в стандартном SQL, если не рассматриваются как идентификаторы с разделителями; для настоящих целей тире меняются на подчеркивания.

В этом методе используется базовый SQL. Он не использует расширения ROLAP и не использует предложения WITH, которые дают имена общим выражениям.

Сколько раз каждый пользователь заходил на каждый веб-сайт?

SELECT User_ID, Website_ID, COUNT(*) AS NumberOfVisits
  FROM WebSitesVisited
 GROUP BY User_ID, Website_ID;

Какое максимальное количество раз пользователь посещал какой-либо веб-сайт?

SELECT User_ID, MAX(NumberOfVisits) AS MaxNumberOfVisits
  FROM (SELECT User_ID, Website_ID, COUNT(*) AS NumberOfVisits
          FROM WebSitesVisited
         GROUP BY User_ID, Website_ID
       ) AS V
 GROUP BY User_ID;

Какие веб-сайты посещал данный пользователь чаще всего?

SELECT V.User_ID, V.Website_ID, V.NumberOfVisits
  FROM (SELECT User_ID, MAX(NumberOfVisits) AS MaxNumberOfVisits
          FROM (SELECT User_ID, Website_ID, COUNT(*) AS NumberOfVisits
                  FROM WebSitesVisited
                 GROUP BY User_ID, Website_ID
               ) AS V2
         GROUP BY User_ID
       ) AS M
  JOIN (SELECT User_ID, Website_ID, COUNT(*) AS NumberOfVisits
          FROM WebSitesVisited
         GROUP BY User_ID, Website_ID
       ) AS V
    ON M.User_ID = V.User_ID AND M.NumberOfVisits = V.MaxNumberOfVisits
 ORDER BY V.User_ID;

Обратите внимание, что если пользователь X посещал как сайт Y, так и сайт Z одинаковое количество раз (и это число было наибольшим, когда пользователь X посещал какой-либо сайт), то и Y, и Z появятся в списке для пользователя X.

0 голосов
/ 22 января 2011

Это может показаться сложным, но оно будет агрегировать данные только один раз , затем проходить через них, ранжируя результаты и выбирая только первое

select userid, websiteid, visits
from
(
select 
 userid, websiteid, visits,
 @r := case when @u=userid then @r+1 else 1 end r,
 @u := userid
from
(select @u:=null) x,
(select userid, websiteid, count(*) visits
 from visit
 group by userid, websiteid
 order by userid, visits desc) y
) z
where r=1

Внутренний выбор генерирует счетчики для каждой комбинации пользователь-веб-сайт и упорядочивает ее по большинству посещений. Затем он проходит через средний запрос, который ранжирует записи per user, давая ранг в столбце r.

Это вариант, который покажет ВСЕ веб-сайты для пользователя, имеющего РАВНЫЙ ранг. Разница с предыдущим запросом состоит в том, что если веб-сайты A и B имеют 10 посещений от пользователя X, в результате будут указаны и A, и B, тогда как предыдущий запрос выбирает один случайным образом для отображения.

select userid, websiteid, visits
from
(
select 
 userid, websiteid, visits,
 @r := case
    when @u=userid and @v=visits then @r  # same rank
    when @u=userid then @r+1              # next rank
    else 1                                # different user
    end r,
 @u := userid, @v := visits
from
(select @u:=null, @v:=null) x,
(select userid, websiteid, count(*) visits
 from visit
 group by userid, websiteid
 order by userid, visits desc) y
) z
where r=1

Это тестовая таблица, используемая

create table visit (userid int, websiteid int);
insert into visit select 1,1;
insert into visit select 1,2;
insert into visit select 1,1;
insert into visit select 1,4;
insert into visit select 2,1;
insert into visit select 2,2;
insert into visit select 2,5;
insert into visit select 2,2;
0 голосов
/ 21 января 2011

Я не уверен, что правильно понял ваш вопрос. Если вы хотите получить идентификатор веб-сайта с наибольшим количеством посещений, вы можете использовать это:

select count(user-ID) as cnt from dataTable group by website-ID order by cnt desc
...