Mysql извлекает все узлы в иерархии и суммирует их личные и групповые продажи - PullRequest
0 голосов
/ 11 апреля 2020

У меня есть таблица со всеми менеджерами по продажам и их менеджером по продажам со следующей структурой:
user_id, manager_id
2,1
3,1
4,3
5, 2
6,5


Если я ищу менеджера 1, я получу список
2
3
4
5
6
Поскольку все они находятся под менеджером 1

Если я ищу менеджера 2, я получу
5,
6

Если я ищу менеджера 3, я получу
4

Мне удалось получить список с помощью запроса ниже:

        SELECT  user_id
        FROM    (SELECT user_id, manager_id FROM tbl_member
                 ORDER BY manager_id, user_id) products_sorted,
                (SELECT @pv := '" . $user_id . "') initialisation
        WHERE   FIND_IN_SET(manager_id, @pv) > 0
        AND     @pv := CONCAT(@pv, ',', user_id)

Сейчас У меня есть другая таблица продаж, которая имеет следующую структуру:
cust_id, sales_amount, user_id

Пример данных:
a001, 100, 2
a002, 200, 3
a003, 150, 1
a004, 200, 5
a005, 100, 4
a005, 80, 6
a006, 50, 1

Могу ли я использовать JOIN с запросом sql, указанным выше, чтобы получить следующие данные:
1) Сумма sales_amount конкретного user_id * 1 051 * 2) Общая группа продаж user_id (включая все узлы, исключая личные продажи)

Пример, если я ищу user_id 1, я хочу получить следующие данные
формат (user_id, personal_sales, group_sales)
2, 100, 280
3, 200, 100
4, 100, 0
5, 200, 80
6, 80, 0

В настоящее время я использую несколько циклов while для вычисления данных ...

$userSales = $this->getUserSales($rows['user_id'], $startDate, $endDate);            
$groupSales  = $this->getGroupSales($rows['user_id'], $startDate, $endDate);

В функции getGroupSales я снова запускаю следующий запрос

    SELECT  user_id
    FROM    (SELECT user_id, manager_id FROM tbl_member
             ORDER BY manager_id, user_id) products_sorted,
            (SELECT @pv := '" . $user_id . "') initialisation
    WHERE   FIND_IN_SET(manager_id, @pv) > 0
    AND     @pv := CONCAT(@pv, ',', user_id)

для извлечения всех узлов ниже user_id и получения суммы с помощью функции getUserSales () ... которая выполняется безумно медленно. При наличии около 10 000 записей о продажах и 1000 идентификаторов пользователей загрузка страницы составляет более 30 секунд.

Может кто-нибудь посоветовать, как сделать запрос быстрее?

1 Ответ

0 голосов
/ 11 апреля 2020

Вы должны выполнить EXPLAIN для вашего запроса и посмотреть, используются ли все индексы.

. Для вашего SUM я бы использовал следующий запрос и использовал бы индексы, которые вы видите в примере.

Вы можете также использовали комбинированные индексы, например, для user_id и временного столбца, который вы не показывали.

CREATE TABLE table1 (
  `atexdt` VARCHAR(4),
  `amount` INTEGER,
  `refuser_id` INTEGER
  ,INDEX(refuser_id)
);

INSERT INTO table1
  (`atexdt`, `amount`, `refuser_id`)
VALUES
  ('a001', '100', '2'),
  ('a002', '200', '3'),
  ('a003', '150', '1'),
  ('a004', '200', '5'),
  ('a005', '100', '4'),
  ('a005', '80', '6'),
  ('a006', '50', '1');

CREATE TABLE u_m (
  `user_id` INTEGER,
  `manager_id` INTEGER
  ,INDEX(user_id)
,INDEX(manager_id)
);

INSERT INTO u_m
  (`user_id`, `manager_id`)
VALUES
  ('2', '1'),
  ('3', '1'),
  ('4', '3'),
  ('5', '2'),
  ('6', '5');
✓

✓

✓

✓
SELECT
u1.user_id,
SUM(t1.amount)
,MAX(sumgroup)
FROM 
  table1 t1 
INNER JOIN 
  u_m u1 ON t1.refuser_id = u1.user_id
INNER JOIN 
  (SELECT SUM(t1.amount) sumgroup, `manager_id` FROM   table1 t1 
          INNER JOIN 
          u_m ON t1.refuser_id = u_m.user_id 
          GROUP BY `manager_id`) u2
  ON u1.manager_id = u2.manager_id
WHERE u1.user_id IN (1,2,3,4,5,6)
GROUP BY u1.user_id 
user_id | SUM(t1.amount) | MAX(sumgroup)
------: | -------------: | ------------:
      2 |            100 |           300
      3 |            200 |           300
      4 |            100 |           100
      5 |            200 |           200
      6 |             80 |            80

db <> fiddle здесь

ОБЪЯСНЕНИЕ этого запроса

id | select_type | table      | partitions | type | possible_keys      | key        | key_len | ref                       | rows | filtered | Extra                                             
-: | :---------- | :--------- | :--------- | :--- | :----------------- | :--------- | :------ | :------------------------ | ---: | -------: | :-------------------------------------------------
 1 | PRIMARY     | <derived2> | <em>null</em>       | ALL  | <em>null</em>               | <em>null</em>       | <em>null</em>    | <em>null</em>                      |    5 |   100.00 | Using temporary; Using filesort                   
 1 | PRIMARY     | u1         | <em>null</em>       | ALL  | user_id,manager_id | <em>null</em>       | <em>null</em>    | <em>null</em>                      |    5 |    25.00 | Using where; Using join buffer (Block Nested Loop)
 1 | PRIMARY     | t1         | <em>null</em>       | ref  | refuser_id         | refuser_id | 5       | db_1517119808.u1.user_id  |    1 |   100.00 | <em>null</em>                                              
 2 | DERIVED     | u_m        | <em>null</em>       | ALL  | user_id,manager_id | <em>null</em>       | <em>null</em>    | <em>null</em>                      |    5 |   100.00 | Using where; Using temporary; Using filesort      
 2 | DERIVED     | t1         | <em>null</em>       | ref  | refuser_id         | refuser_id | 5       | db_1517119808.u_m.user_id |    1 |   100.00 | <em>null</em>                                              
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...