"Ortak Sevdikleri" SQL sorgusu oluşturmak için nasıl

5 Cevap php

Currently I'm building a system (php and mysql), that on the user profile allows you to add "favorite music artists" to a list. 've been trying to figure out a way to compare the user likes to other users and return a "recommended friends".

Örneğin:

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

Daha sonra bu kullanıcı ile şu öneriyi almak olacaktır:

User C
User B

Benim tahminim bir İlişkisel Veritabanı yapmak ve kullanıcı girişi çoğu standardize etmek gerekir bunu yapmak mümkün olmasıdır.

So my questions are: What Database structure is the best for this kind of comparisons? What kind of query should I use? (doesn't need to be exact)

5 Cevap

Doğrudan değil, bir sorunuzun cevabı ancak kitap kontrol etmek isteyebilirsiniz Programming Collective Intelligence. Sorunuzun dayanarak ben çok yararlı buluyorum düşünüyorum.

Basit bir uygulama gibi görünebilir

CREATE TABLE user_tbl(
    user_id BIGINT,
    ...
)

CREATE TABLE music_tbl(
    music_id BIGINT,
    ...
)

CREATE TABLE likes_tbl(
    user_id BIGINT,
    music_id BIGINT
)

Bunu yapmak, belirli bir kullanıcıya benzer bir tadı olan tüm kullanıcıları bulmak için:

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

Rl kullanıcıların kolonda sanatçıların sayısı, bu nedenle daha yüksek bir ağırlık, daha fazla ortak. Yani heighest ağırlığı ile en iyi 5 kullanıcılara tavsiye olabilir.

Bu, farklı şekillerde uzatılabilir. Bir olasılık music_tbl ve likes_tbl bir genre_id eklemek ve sonra genre_id üzerinde katılırım olduğunu.

Önceden gönderilmiş ne çoğaltmak, için değil ama ...

--
-- 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;

İyi şanslar!

Kullanıcı ve favorited sanatçı: Bir Sanatçılar tablo ve bir Kullanıcılar tablo varsa, iki yabancı anahtarlar ile bir tablo FavoriteArtists olabilir.

Sonra sadece benzer sıktınız ve bazı eşik örtüşme dayalı kullanıcıya arkadaşlar tavsiye diğer kullanıcıları olsun.

Tables

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

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

UserSong
userid
songid

Query

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'

Less Verbose Query Using a Natural Join

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

(Yanılıyorsam Birisi beni düzeltin. Bunu bir test değil unutmayın, henüz.)

Yukarıdaki sorgu size verilen sanatçı "gibi" tüm kullanıcıların bir listesini verecektir. Daha sonra başka ne yaptıklarını seven diğer kullanıcılara göstermek için bu listeyi kullanabilirsiniz.