Como criar consulta SQL para “Curtir em comum”
-
06-07-2019 - |
Pergunta
Atualmente estou construindo um sistema (php e mysql), que no perfil do usuário permite que você adicione "artistas de música favoritos" a uma lista. Estiveram tentando descobrir uma maneira de comparar o usuário gosta de outros usuários e retornar uma 'amigos recomendados'.
Por exemplo:
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
Em seguida, com este usuário teria a seguinte recomendação:
User C
User B
Meu palpite é que, para ser capaz de fazer isso necessidade I de fazer um banco de dados relacional e padronizar a maior parte da entrada do usuário.
Então, minhas perguntas são: Qual a estrutura de banco de dados é o melhor para este tipo de comparações? Que tipo de consulta que eu deveria usar? (Não precisa ser exato)
Solução
Não diretamente uma resposta à sua pergunta, mas você pode querer verificar o livro Programação Collective Intelligence . Baseado em sua pergunta que eu acho que você iria encontrá-lo muito útil.
Outras dicas
Uma implementação simples pode ter esta aparência
CREATE TABLE user_tbl(
user_id BIGINT,
...
)
CREATE TABLE music_tbl(
music_id BIGINT,
...
)
CREATE TABLE likes_tbl(
user_id BIGINT,
music_id BIGINT
)
Para encontrar todos os usuários que têm sabor semelhante a um determinado utilizador que faça o seguinte:
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
A coluna de peso é o número de artistas que os usuários têm na coluna, por isso quanto maior o peso, mais eles têm em comum. Então você pode recomendar o top 5 usuários com o peso heighest.
Isso pode ser estendido de maneiras diferentes. Uma possibilidade é adicionar um genre_id ao music_tbl e likes_tbl e, em seguida, fazer a junção em genre_id.
Para não repetir o que já foi publicado, mas ...
--
-- 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;
Boa sorte!
Se você tiver uma mesa de Artistas e uma tabela de usuários, você pode ter um FavoriteArtists mesa com duas chaves estrangeiras:. O usuário, eo artista Favorito
Em seguida, basta obter outros usuários que têm favoritos semelhantes e recomendar amigos para o usuário com base em alguma sobreposição limiar.
Tabelas
User
userid int
FirstName varchar(30)
LastName varchar(30)
Song
songid int
Title varchar(30)
Artist varchar(30)
UserSong
userid
songid
Consulta ??strong>
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'
Menos detalhado Consulta Usando um Natural Junte-se
select User.userid, User.FirstName, User.LastName
from UserSong
natural join Song
natural join User
where Song.Artist='Some Artist'
(Note que eu não testei este, ainda. Alguém me corrija se eu estiver errado).
A consulta acima lhe dará uma lista de todos os usuários que "como" o artista dado. Você pode então usar essa lista para mostrar aos outros quem mais gosta do que eles fazem.
No 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 )
consulta para selecionar os usuários com os mesmos gostos:
SELECT
FROM FavoriteArtists u, FavoriteArtists f
WHERE u.ArtistID = f.ArtistID AND u.UserID = @TARGET_USER AND f.UserID <> @TARGET_USER