Проблема вычисления запроса MySQL после LEFT JOIN - PullRequest
0 голосов
/ 28 октября 2018

У меня есть две таблицы user_point_logs и user_point_used_logs оттуда я хочу получить такой вывод

╔══════╦═════╦══════════════════════╦═══════════════════════╗══════════════╗
║ year ║month║ user_next_expire_date║ user_point_next_expire║minus         ║
╠══════╬═════╬══════════════════════╬═══════════════════════╣══════════════╣
║2018  ║ 10  ║ 2018年10月27日        ║ 200                   ║110          ║
║      ║     ║                      ║                       ║              ║ 
╚══════╩═════╩══════════════════════╩═══════════════════════╝══════════════╝

здесь есть отношение user_point_logs.return_id= user_point_used_logs.id и user_point_used_logs.user_point_log_used_id = user_point_logs.id

user_point_logs таблица

╔════╦════════╦═════╦═══════════╦══════════╗
║ id ║user_id ║point║expire_date║return_id ║
╠════╬════════╬═════╬═══════════╬══════════╣
║  1 ║ 16087  ║ 100 ║1540649153 ║   null   ║
║  2 ║ 16087  ║ 100 ║ null      ║   1      ║
║  3 ║ 16087  ║ 10  ║ null      ║   2      ║
║  4 ║ 16087  ║ 100 ║ 1540649153║   null   ║ 
╚════╩════════╩═════╩═══════════╩══════════╝

Таблица user_point_used_logs :

|-------|-----------------------|-----------------------|------|
| Id    | user_point_log_id     | user_point_log_used_id| point|
|-------|-----------------------|-----------------------|------|
| 1     |         2             |         2             | 100  |
|-------|-----------------------|-----------------------|------|
| 2     |         3             |         3             | 10   |
|-------|-----------------------|-----------------------|------|

Я только что попытался разместить некоторые примеры данных.Вот мой запрос.

SELECT 
  YEAR(FROM_UNIXTIME(user_point_logs.expire_date, '%Y-%m-%d')) AS year, 
  MONTH(FROM_UNIXTIME(user_point_logs.expire_date, '%Y-%m-%d')) AS month, 
  FROM_UNIXTIME(
    SUBSTRING_INDEX(
      GROUP_CONCAT(
        DISTINCT user_point_logs.expire_date ORDER BY user_point_logs.expire_date ASC
        SEPARATOR ','
      ), 
      ',', 
      1
    ), 
    '%Y年%m月%d日'
  ) AS user_next_expire_date, 
  SUM(user_point_logs.point) AS user_point_next_expire, 
  IF(
    SUM(`user_point_used_logs`.`point`) IS NULL, 
    0, 
    SUM(`user_point_used_logs`.`point`) 
  ) AS `minus` 
FROM `user_point_logs` 
LEFT JOIN (
  SELECT *
  FROM user_point_used_logs
  WHERE user_point_log_id NOT IN (
    SELECT DISTINCT return_id
    FROM user_point_logs
    WHERE return_id IS NOT NULL
  )
) AS user_point_used_logs 
ON (`user_point_logs`.`id` = `user_point_used_logs`.`user_point_log_used_id`) 
WHERE `user_point_logs`.`user_id` = '16087' 
AND `user_point_logs`.`point` > 0
AND `user_point_logs`.`expire_date` > 1540464465 
AND (
  `user_point_logs`.`return_id` = 0 OR 
  `user_point_logs`.`return_id` IS NULL
)
GROUP BY `year`, `month`

Проблема в том, что иногда вычисление оставшейся точки и минуса не дает реального результата.В моей скрипке вы увидите user_point_next_expire 200, но минус 0. Но там должно быть минус 100.

Скажите, пожалуйста, есть ли что-то не так в моем запросе или нет.

Вот мой примернабор данных ...

CREATE TABLE user_point_logs (
  id          int NOT NULL,
  user_id     int NOT NULL,
  point       int(11) NOT NULL,
  expire_date int DEFAULT NULL,
  return_id   int DEFAULT NULL
);

CREATE TABLE user_point_used_logs (
  id                      int NOT NULL,
  user_point_log_id       int NOT NULL,
  user_point_log_used_id  int DEFAULT '0' ,
  point                   int NOT NULL 
);

INSERT INTO user_point_used_logs 
  (id,  user_point_log_id,  user_point_log_used_id, point) 
VALUES 
  (1,   2,                  2,                      100),
  (2,   3,                  3,                      10);

INSERT INTO user_point_logs 
  (id,  user_id,  point,  expire_date,  return_id) 
VALUES
  (1,   16087,    100,    1540649153,   NULL),
  (2,   16087,    100,    NULL      ,   1   ),
  (3,   16087,     10,    NULL      ,   2   ),
  (4,   16083,    100,    1540649153,   NULL),
  (5,   16087,    100,    1540649153,   NULL);

.. и скрипка того же

1 Ответ

0 голосов
/ 28 октября 2018

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

SELECT MAX(FROM_UNIXTIME(expire_date)) dt
     , SUM(CASE WHEN expire_date < UTC_TIMESTAMP() THEN point END) a
     , SUM(CASE WHEN expire_date IS NULL THEN point END) b
  FROM user_point_logs
 WHERE user_id = 16087
 GROUP 
    BY user_id;
...