Question

Cette table stocke les votes des utilisateurs entre les correspondances des utilisateurs. Il y a toujours un gagnant, un perdant et l'électeur.

CREATE TABLE `user_versus` (
  `id_user_versus` int(11) NOT NULL AUTO_INCREMENT,
  `id_user_winner` int(10) unsigned NOT NULL,
  `id_user_loser` int(10) unsigned NOT NULL,
  `id_user` int(10) unsigned NOT NULL,
  `date_versus` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id_user_versus`),
  KEY `id_user_winner` (`id_user_winner`,`id_user_loser`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=17 ;

INSERT INTO `user_versus` (`id_user_versus`, `id_user_winner`, `id_user_loser`, `id_user`, `date_versus`) VALUES
(1, 6, 7, 1, '2013-10-25 23:02:57'),
(2, 6, 8, 1, '2013-10-25 23:02:57'),
(3, 6, 9, 1, '2013-10-25 23:03:04'),
(4, 6, 10, 1, '2013-10-25 23:03:04'),
(5, 6, 11, 1, '2013-10-25 23:03:10'),
(6, 6, 12, 1, '2013-10-25 23:03:10'),
(7, 6, 13, 1, '2013-10-25 23:03:18'),
(8, 6, 14, 1, '2013-10-25 23:03:18'),
(9, 7, 6, 2, '2013-10-26 04:02:57'),
(10, 8, 6, 2, '2013-10-26 04:02:57'),
(11, 9, 8, 2, '2013-10-26 04:03:04'),
(12, 9, 10, 2, '2013-10-26 04:03:04'),
(13, 9, 11, 2, '2013-10-26 04:03:10'),
(14, 9, 12, 2, '2013-10-26 04:03:10'),
(15, 9, 13, 2, '2013-10-26 04:03:18'),
(16, 9, 14, 2, '2013-10-26 04:03:18');

Je travaille sur une requête qui récupère des profils similaires. Un profil est similaire, lorsque le pourcentage de vote (gagne vs perd) est de +/- 10% du profil spécifié.

SELECT id_user_winner AS id_user,
    IFNULL(wins, 0) AS wins,
    IFNULL(loses, 0) AS loses,
    IFNULL(wins, 0) + IFNULL(loses, 0) AS total,
    IFNULL(wins, 0) / (IFNULL(wins, 0) + IFNULL(loses, 0)) AS percent
FROM
(
    SELECT id_user_winner AS id_user FROM user_versus 
    UNION
    SELECT id_user_loser FROM user_versus 
) AS u
LEFT JOIN
(
    SELECT id_user_winner, COUNT(*) AS wins
    FROM user_versus
    GROUP BY id_user_winner
) AS w
ON u.id_user = id_user_winner
LEFT JOIN
(
    SELECT id_user_loser, COUNT(*) AS loses
    FROM user_versus
    GROUP BY id_user_loser
) AS l
ON u.id_user = l.id_user_loser

C'est le résultat actuel:

mysql result

Il revient actuellement des lignes nuls, et ils ne devraient pas être là. Ce qui doit encore être optimisé (et je ne peux pas tout à fait mettre mon doigt dessus) est:

  1. Amenez les utilisateurs similaires à l'utilisateur ABC uniquement
  2. Spécifiez la condition qui définit qui est un utilisateur similaire, par exemple, ID utilisateur = 6 (où les utilisateurs similaires ont +/- 10% de différence de pourcentage avec l'ID utilisateur 6)

Toute aide serait appréciée. Merci!

Était-ce utile?

La solution

Pour calculer les victoires et les pertes de chaque utilisateur sans avoir à rejoindre le tableau à lui-même et à utiliser des jointures externes, il est possible de sélectionner des victoires et des pertes séparément et de faire une union entre elles, mais avec des informations supplémentaires si la ligne donne une victoire pour l'utilisateur, ou une perte.

Ensuite, il est facile de calculer toutes les victoires et pertes pour chaque utilisateur. La partie délicate consistait à incorporer l'option pour spécifier à quel utilisateur vous souhaitez comparer les profils. Je l'ai fait avec une variable qui est définie sur la valeur de percentage de l'utilisateur avec donné user_id, que vous pouvez passer d'une constante à une variable.

Voici ma proposition (par rapport à l'utilisateur avec id = 6):

SELECT
    player_id AS id_user,
    wins,
    losses,
    wins + losses AS total,
    wins / (wins + losses) AS percent
  FROM (
    SELECT
        player_id,
        SUM(is_a_win) wins,
        SUM(is_a_loss) losses,
        CASE
          WHEN player_id = 6
            THEN @the_user_score := SUM(is_a_win) / (SUM(is_a_win) + SUM(is_a_loss))
          ELSE NULL
         END
      FROM (
        SELECT id_user_winner AS player_id, 1 AS is_a_win, 0 AS is_a_loss FROM user_versus
        UNION ALL SELECT id_user_loser, 0, 1 FROM user_versus
      ) games
    GROUP BY player_id
  ) data
WHERE
  ABS(wins / (wins + losses) - @the_user_score) <= 0.1
;

Production:

ID_USER WINS   LOSSES  TOTAL   PERCENT
6       8       2       10      0.8
9       6       1       7       0.8571

Vous pouvez bien sûr supprimer l'utilisateur dont le profil est la base de comparaison en ajoutant player_id != 6 (ou, dans la solution finale, un nom de variable) WHERE clause.

Exemple à Sqlfiddle: Profils correspondants - Exemple

Pourriez-vous fournir des commentaires si c'est ce que vous recherchiez et, sinon, quelle sortie vous attendriez-vous?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top