Как создать SQL-запрос для "Likes in common" - PullRequest
2 голосов
/ 24 октября 2009

В настоящее время я строю систему (php и mysql), которую в профиле пользователя можно добавить «Любимые исполнители музыки» в список. пытаюсь найти способ сравнить лайки пользователей с другими пользователями и вернуть «рекомендуемых друзей».

Например:

User A Likes
- 1
- 2
- 3
- 4

User B Likes
- 1 <- A likes
- 5
- 6
- 7

User C Likes
- 1 <- A likes
- 2 <- A likes
- 8
- 9

Тогда с этим пользователем A получит следующую рекомендацию:

User C
User B

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

Итак, мои вопросы: Какая структура базы данных является лучшей для такого рода сравнений? Какой запрос я должен использовать? (не нужно быть точным)

Ответы [ 6 ]

4 голосов
/ 24 октября 2009

Не является прямым ответом на ваш вопрос, но вы можете почитать книгу Программирование Коллективного разума . На основании вашего вопроса, я думаю, вы найдете его очень полезным.

2 голосов
/ 24 октября 2009

Не дублировать то, что уже было опубликовано, но ...

--
-- Working MySQL implementation of a "user compatibility" schema.
--


DROP TABLE IF EXISTS favourite;
DROP TABLE IF EXISTS artist;
DROP TABLE IF EXISTS users;


CREATE TABLE users (
 user_id INT NOT NULL AUTO_INCREMENT,
 name VARCHAR(32),
 PRIMARY KEY (user_id)
);


CREATE TABLE artist (
 artist_id INT NOT NULL AUTO_INCREMENT,
 name VARCHAR(32),
 PRIMARY KEY (artist_id)
);


CREATE TABLE favourite (
 favourite_id INT NOT NULL AUTO_INCREMENT,
 user_id INT NOT NULL,
 artist_id INT NOT NULL,
 UNIQUE (user_id, artist_id),
 PRIMARY KEY (favourite_id),
 FOREIGN KEY (user_id) REFERENCES users (user_id) ON DELETE CASCADE,
 FOREIGN KEY (artist_id) REFERENCES artist (artist_id) ON DELETE CASCADE
);


INSERT INTO users
 (name)
VALUES
 ("Alice"),
 ("Bob"),
 ("Carol"),
 ("Dave")
;


INSERT INTO artist
 (name)
VALUES
 ("Jewel"),
 ("Sarah McLachlan"),
 ("Britney Spears"),
 ("David Bowie"),
 ("The Doors")
;


INSERT INTO favourite
 (user_id, artist_id)
VALUES
 (
  (SELECT user_id FROM users WHERE name = "Alice"),
  (SELECT artist_id FROM artist WHERE name = "Jewel")
 ),
 (
  (SELECT user_id FROM users WHERE name = "Alice"),
  (SELECT artist_id FROM artist WHERE name = "Sarah McLachlan")
 ),
 (
  (SELECT user_id FROM users WHERE name = "Bob"),
  (SELECT artist_id FROM artist WHERE name = "Jewel")
 ),
 (
  (SELECT user_id FROM users WHERE name = "Bob"),
  (SELECT artist_id FROM artist WHERE name = "Sarah McLachlan")
 ),
 (
  (SELECT user_id FROM users WHERE name = "Bob"),
  (SELECT artist_id FROM artist WHERE name = "Britney Spears")
 ),
 (
  (SELECT user_id FROM users WHERE name = "Bob"),
  (SELECT artist_id FROM artist WHERE name = "David Bowie")
 ),
 (
  (SELECT user_id FROM users WHERE name = "Carol"),
  (SELECT artist_id FROM artist WHERE name = "David Bowie")
 ),
 (
  (SELECT user_id FROM users WHERE name = "Carol"),
  (SELECT artist_id FROM artist WHERE name = "The Doors")
 ),
 (
  (SELECT user_id FROM users WHERE name = "Dave"),
  (SELECT artist_id FROM artist WHERE name = "Jewel")
 ),
 (
  (SELECT user_id FROM users WHERE name = "Dave"),
  (SELECT artist_id FROM artist WHERE name = "The Doors")
 )
;


SELECT
 t0.user_id myuser,
 t1.user_id friend,
 COUNT(*)
FROM favourite t0
JOIN favourite t1 ON t1.artist_id = t0.artist_id
WHERE t0.user_id != t1.user_id
GROUP BY t0.user_id, t1.user_id;


--
-- The same thing, but returning names!
--

SELECT
 t0u.name myuser,
 t1u.name friend,
 COUNT(*)
FROM favourite t0
JOIN favourite t1 ON t1.artist_id = t0.artist_id
JOIN users t0u ON t0u.user_id = t0.user_id
JOIN users t1u ON t1u.user_id = t1.user_id
WHERE t0.user_id != t1.user_id
GROUP BY t0.user_id, t1.user_id;

Удачи!

2 голосов
/ 24 октября 2009

Простая реализация может выглядеть следующим образом

CREATE TABLE user_tbl(
    user_id BIGINT,
    ...
)

CREATE TABLE music_tbl(
    music_id BIGINT,
    ...
)

CREATE TABLE likes_tbl(
    user_id BIGINT,
    music_id BIGINT
)

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

select u1.user_id, u2.user_id, count(*) as weight from likes_tbl u1, likes_tbl u2
where u1.music_id = u2.music_id and u1.user_id <> u2.user_id and u1.user_id = @user_id
group by u1.user_id, u2.user_id

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

Это может быть расширено различными способами. Одна из возможностей - добавить genre_id в music_tbl и likes_tbl, а затем выполнить соединение для genre_id.

1 голос
/ 24 октября 2009

Таблица

User
userid int
FirstName varchar(30)
LastName varchar(30)

Song
songid int
Title varchar(30)
Artist varchar(30)

UserSong
userid
songid

Запрос

select User.userid, User.FirstName, User.LastName
from UserSong
inner join Song
on UserSong.songid=Song.songid
inner join User
on UserSong.userid=User.userid
where Song.Artist='Some Artist'

Меньше многословных запросов с использованием естественного соединения

select User.userid, User.FirstName, User.LastName
from UserSong
natural join Song
natural join User
where Song.Artist='Some Artist'

(Обратите внимание, что я еще не проверял это. Кто-то исправит меня, если я ошибаюсь.)

Приведенный выше запрос даст вам список всех пользователей, которым «нравится» данный исполнитель. Затем вы можете использовать этот список, чтобы показать другим пользователям, кому еще нравится то, что они делают.

1 голос
/ 24 октября 2009

В SQL Server:

CREATE TABLE Users (
UserID BIGINT IDENTITY (1,1) NOT NULL
--Other columns here
)


CREATE TABLE Artists (
ArtistID BIGINT IDENTITY(1,1) NOT NULL
-- Other columns
)


CREATE TABLE FavoriteArtists (
UserID BIGINT, ArtistID BIGINT )

запрос для выбора пользователей с такими же лайками:

SELECT 
FROM   FavoriteArtists u, FavoriteArtists f
WHERE  u.ArtistID = f.ArtistID AND u.UserID = @TARGET_USER AND f.UserID <> @TARGET_USER
1 голос
/ 24 октября 2009

Если у вас есть таблица Artists и таблица Users, вы можете иметь таблицу FavoriteArtists с двумя внешними ключами: пользователь и предпочитаемый исполнитель.

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

...