Сложный запрос MySQL для одной таблицы - PullRequest
1 голос
/ 10 августа 2011

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

Вот таблица

    CREATE TABLE `users` (
  `id` int(11) NOT NULL auto_increment,
  `firstname` varchar(64) NOT NULL,
  `lastname` varchar(64) NOT NULL,
  `email` varchar(64) NOT NULL,
  `status` smallint(5) NOT NULL,
  `refchid1` int(11) NOT NULL,
  `refchid2` int(11) NOT NULL,
  `refchid3` int(11) NOT NULL,
  `refchid4` int(11) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 ;

Пояснение:

  1. Я пытаюсь настроить статус человека на основе сложного дерева. У каждого пользователя есть идентификатор, обозначенный в поле идентификатора auto_increment.
  2. Пользователь A вводит свои данные в таблицу.
  3. Пользователь B упоминается пользователем A, поэтому при вводе его данных refchid1 имеет тот же идентификатор, что и пользователь A.
  4. Пользователь C упоминается пользователем B, его refchid1 становится идентификатором пользователя B, а его refchid2 становится идентификатором пользователя A.
  5. Пользователь D ссылается на пользователя C, его refchid1 становится таковым для пользователя C, refchid2 - для пользователя B, а refchid3 - для пользователя A.

Если вы понимаете ссылки на вышесказанное, вы на правильном пути.

Пример данных приведенного выше описания:

(6, 'Lars', 'Luna', 'Morbi.non.sapien@enimgravida.com', 25, 0, 0, 0, 0),
(7, 'Sonya', 'Cox', 'tellus@orci.org', 25, 6, 0, 0, 0),
(8, 'Aiko', 'Hodge', 'vestibulum.neque.sed@vel.edu', 25, 7, 6, 0, 0),
(9, 'Lillith', 'Bray', 'purus.Duis.elementum@necurnasuscipit.org', 25, 8, 7, 6, 0),
(10, 'Macey', 'Hayes', 'mi.pede@aliquetodioEtiam.net', 25, 9, 8, 7, 6);

Что я пытаюсь сделать, это:

  1. Статус по умолчанию - 25. (25,28,30,35,40). В основном это система скидок, где чем больше людей вы ссылаетесь и чем больше людей ссылаются на вас, где вы являетесь исходным реферером, тем больше вы получаете скидки.
  2. Если у пользователя А есть как минимум 10 уникальных пользователей, на которых он ссылается как refchid1, он получает статус.
  3. Если у пользователя A есть как минимум 10 уникальных пользователей в refchid1, каждый из которых по очереди имеет 10 уникальных пользователей в refchid1, где пользователь A является refchid2, он получает статус.
  4. Пользователь A имеет 10 уникальных пользователей в rechid1, каждый из которых имеет 10 уникальных пользователей в refchid1, где пользователь A - это rechid2, которые в свою очередь имеют 10 уникальных пользователей в refchid1, где пользователь A - это refchid3.
  5. и т.д.

Как уже говорилось, структура тестирования сложна, и я хочу сделать это, не перегружая сервер mysql миллионами запросов. Запрос должен быть запросом ОБНОВЛЕНИЯ, который будет корректировать статус всех соответствующих пользователей.

У кого-нибудь есть решение о том, как я собираюсь это сделать?

Ответы [ 3 ]

1 голос
/ 10 августа 2011

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

SELECT
 parent.*,
 SUM(IF(parent.id = child.refchid1, 1, 0)) AS count_ref1,
 SUM(IF(parent.id = child.refchid2, 1, 0)) AS count_ref2,
 SUM(IF(parent.id = child.refchid3, 1, 0)) AS count_ref3,
 SUM(IF(parent.id = child.refchid4, 1, 0)) AS count_ref4,
 COUNT(child.id) as count_ref
FROM users AS parent 
LEFT JOIN users AS child 
    ON (  parent.id = child.refchid1 
       OR parent.id = child.refchid2 
       OR parent.id = child.refchid3 
       OR parent.id = child.refchid4)
GROUP BY parent.id
0 голосов
/ 11 августа 2011

Я должен был создать список пользователей и отдельную таблицу для ссылок,

CREATE TABLE reference
(
    reference_id SERIAL,
    new_user_id BIGINT UNSIGNED NOT NULL,
    refered_user_id BIGINT UNSIGNED NOT NULL,
    reference_depth INT UNSIGNED NOT NULL
);

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

INSERT INTO reference SET
    new_user_id = $new_user_id, 
    refered_user_id =  $refered_user_id, 
    reference_depth = 1

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

INSERT INTO reference (new_user_id, refered_user_id, reference_depth)
SELECT $new_user_id, refered_user_id, reference_depth +1
FROM reference WHERE new_user_id = $refered_user_id;

, а затем рассчитать баллы

SELECT
  SUM(
    IF(reference_depth = 1, 10, 0) 
    + IF(reference_depth = 2, 3, 0) 
    + IF(reference_depth = 3, 2, 0)
    + IF(reference_depth > 3, 1, 0)
  )
FROM reference
WHERE new_user_id = $user_id
0 голосов
/ 10 августа 2011

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

В противном случае я бы рекомендовал не использовать status и refchid * столбцов, а только один refid , который ссылается на «родительский» идентификатор, а затем использовать представление для генерациизначение status (относительно рекурсивного refid).

...