Pregunta

Esta tabla almacena votos de usuario entre las coincidencias de usuarios. Siempre hay un ganador, un perdedor y el votante.

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

Estoy trabajando en una consulta que obtiene perfiles similares. Un perfil es similar, cuando el porcentaje de votación (gana vs pierde) es +/- 10% del perfil especificado.

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

Este es el resultado actual:

mysql result

Actualmente está devolviendo filas nulas, y no deberían estar allí. Lo que aún necesita para optimizar (y no puede decirlo con el dedo) es:

  1. Traiga a los usuarios similares al usuario ABC solamente
  2. Especifique la condición que define a quién es un usuario similar, por ejemplo, ID de usuario = 6 (donde usuarios similares tienen una diferencia de +/- 10% en porcentaje con ID de usuario 6)

Cualquier ayuda será apreciada. ¡Gracias!

¿Fue útil?

Solución

Para calcular las victorias y pérdidas de cada usuario sin tener que unirse a la tabla a sí misma y usar uniones externas, es posible seleccionar victorias y pérdidas por separado y hacer una unión entre ellos, pero con información adicional si se le da una fila representa una victoria para el usuario o una pérdida.

Luego, es fácil calcular todas las victorias y pérdidas para cada usuario. La parte difícil fue incorporar la opción para especificar a qué usuario le gustaría comparar los perfiles. Lo hice con una variable que se establece en el valor de percentage del usuario con dado user_id, que puede cambiar de una constante a una variable.

Aquí está mi propuesta (en comparación con el usuario con 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
;

Producción:

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

Por supuesto, podría eliminar al usuario cuyo perfil es la base para la comparación agregando player_id != 6 (o, en la solución final, algún nombre de variable) con el más externo WHERE cláusula.

Ejemplo en SQLFIDDLE: Perfiles coincidentes - Ejemplo

¿Podría proporcionar algunos comentarios si esto es lo que estaba buscando y, si no, qué salida esperaría?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top