Условная вероятность в SQL - PullRequest
0 голосов
/ 02 декабря 2018

Я думаю, что попал в тупик.

Допустим, у меня есть набор данных, который довольно прост - person_id и book_id.Это довольно фактическая таблица, в которой говорится, что человек X купил книги A, B и C.

Я знаю, как узнать, сколько людей купили Книгу X и Книгу Y вместе.Это

select a.book_id as B1, b.book_id as B2, count(b.person_id) as 
Bought_Together
from dbo.data a 
cross join dbo.data b
where a.book_id != b.book_id and a.person_id = b.person_id
group by a.book_id, b.book_id

И снова мой мозг решил отключиться.Я знаю, что, вероятно, мне нужно было бы сделать это, чтобы count(b.person_id) / all the people that bought book A * 100, но я не совсем уверен.

Надеюсь, я был достаточно ясен.

РЕДАКТИРОВАТЬ1: В настоящее время я использую SQL Server 2017так что я думаю, что правильный ответ - T-SQL ?.В конце формат должен быть чем-то похожим на это.Также нет случаев, когда человек А мог бы купить три копии книги X.

Book1 Book2 HowManyPeopleBoughtBook2
1     2     50%
1     3     7%
2     3     15%
2     1     40%
3     1     60%
3     2     20%

РЕДАКТИРОВАТЬ2: Допустим, в базе данных есть сотни тысяч строк.Да, это связано с курсом по науке о данных, который я прохожу - отсюда и огромное количество данных.

Ответы [ 3 ]

0 голосов
/ 02 декабря 2018

На моем телефоне извинения за опечатки

SELECT
  SUM(bought_b) * 100.0 / COUNT(*)
FROM
(
  SELECT
    person_id, 
    MAX(CASE WHEN book_id = 'A' THEN 1 END)   AS bought_a,
    MAX(CASE WHEN book_id = 'B' THEN 1 END)   AS bought_b
  FROM
    data
  WHERE
    book_id IN ('A', 'B')
  GROUP BY
    person_id
)
  person_stats
WHERE
  bought_a = 1

На моем телефоне извинения за опечатки

РЕДАКТИРОВАТЬ: только что увидел, что вы хотите все комбинации, только одну комбинацию набора.

WITH
  book AS
(
  SELECT DISTINCT book_id FROM data
) 
SELECT
  book_a_id,
  book_b_id,
  bought_b * 100.0 / bought_b
FROM
(
  SELECT
    book_a.book_id    AS book_a_id,
    book_b.book_id    AS book_b_id,
    COUNT(DISTINCT data_a.person_id)    AS bought_a, 
    COUNT(DISTINCT data_b.person_id)    AS bought_b
  FROM
    book    AS book_a
  CROSS JOIN
    book    AS book_b
  INNER JOIN
    data    AS data_a
      ON data_a.book_id = book_a.book_id
  LEFT JOIN
    data    AS data_b
      ON data_b.book_id = book_b.book_id
  GROUP BY
    book_a.book_id,
    book_b.book_id
)
  stats
0 голосов
/ 02 декабря 2018

Вы можете расширить свою логику, чтобы сделать это:

select a.book_id as B1, b.book_id as B2,
       count(b.book_id) as bought_second_book,
       count(b.book_id) * 1.0 / book_cnt as ratio_Bought_Together
from (select a.*, count(*) over (partition by a.book_id) as book_cnt
      from dbo.data a
     ) a left join
     dbo.data b
     on a.person_id = b.person_id and a.book_id <> b.book_id
group by a.book_id, b.book_id, a.book_cnt;

Это предполагает, что люди покупают книгу только один раз.Если есть дубликаты, то count(distinct) будет корректироваться для этого.

0 голосов
/ 02 декабря 2018

Если вы хотите сгенерировать все возможные комбинации пар книг, купленных вместе, и процент лиц, купивших эту комбинацию, то может помочь следующее:

create table data1(book_id int, person_id int)

insert into data1
select *
from (values(1,300)
           ,(2,300)
           ,(2,301)
           ,(1,301)
           ,(3,301)
     )t(book_id,person_id)  

with books
  as (select distinct book_id
        from data1 a
      )
   ,tot_persons
    as (select count(distinct person_id) as tot_cnt
          from data1 
        )
   ,pairs
    as ( 
   select a.book_id as col1 /* This block generates all possible pair combinations of books*/
         ,b.book_id as col2
     from books a
     join books b
       on a.book_id<b.book_id
       )
       select a.col1,a.col2
              ,count(b.person_id)*100/(select tot_cnt from tot_persons) as percent_of_persons_buying_both
         from pairs a
         join data1 b 
           on a.col1=b.book_id  
        where exists(select 1
                       from data1 b1
                      where b.person_id=b1.person_id
                        and a.col2=b1.book_id)
        group by a.col1,a.col2                 
...