MySQL пользовательский вывод на некоторые значения - PullRequest
0 голосов
/ 03 ноября 2018

У меня есть две проблемы, которые мне не удается решить.

  1. Показать разницу между значениями двух ячеек из разных таблиц
  2. Отображение пользовательского вывода на основе количества строк, возвращенных в подзапросе, и / или значения ячейки

В этом конкретном случае у меня есть несколько таблиц, которые необходимо объединить и объединить с пользовательскими выводами в одном запросе MySQL.

Таблицы, лишенные ненужных столбцов и с поддельными данными:

transactions
+----+-------------+------------+--------+
| id | vendor_id   | payment_id | amount |
+----+-------------+------------+--------+
| 1  | 12          | 45         | 25     |
| 2  | 13          | 46         | 50     |
| 3  | 14          | 47         | 50     |
| 4  | 15          | 48         | 50     |
+----+-------------+------------+--------+

vendors
+-----+-------------+
| id  | vendor_code |
+-----+-------------+
| 12  | abc123      |
| 13  | efg321      |
| 14  | hjk456      |
| 15  | fed789      |
+-----+-------------+

payments
+-----+-------+--------+
| id  | order | amount |
+-----+-------+--------+
| 45  | 0032  | 25     |
| 46  | 0063  | 50     |
| 47  | 0073  | 50     |
| 48  | 0087  | 50     |
+-----+-------+--------+

refunds
+----+----------------+--------+
| id | transaction_id | amount |
+----+----------------+--------+
| 65 | 2              | 10     |
+----+----------------+--------+

properties
+-----+----------+
| id  | group_id |
+-----+----------+
| 100 | 222      |
| 200 | 333      |
+-----+----------+

vendor_properties
+----+-------------+------------+
| id | property_id | vendor_id  |
+----+-------------+------------+
| 1  | 100         | 12         |
| 2  | 200         | 12         |
| 3  | 100         | 13         |
| 4  | 200         | 14         |
+----+-------------+------------+

groups
+-----+---------+
| id  | name    |
+-----+---------+
| 222 | groupA  |
| 333 | groupB  |
+-----+---------+

Существуют следующие отношения:

transactions.payment_id -> payments.id
transactions.vendor_id -> vendors.id
payments.vendor_id -> vendors.id
refunds.transaction_id -> transactions.id
properties.property_group_id -> groups.id
vendor_properties.property_id -> properties.id
vendor_properties.vendor_id -> vendors.id

Мой текущий запрос SQL:

SELECT
    `transactions`.`id` AS DB_transID,
    `transactions`.`vendor_id` AS DB_vendID,
    `vendors`.`vendor_code` AS "VendorCode",
    `payments`.`order` AS "Order",
    `transactions`.`amount` AS "Amount"
    `refunds`.`amount` AS "Refunded",
    `groups`.`name` AS "Group"
FROM
    `transactions`
LEFT JOIN
    `payments` ON `payments`.`id` = `transactions`.`payment_id`
LEFT JOIN
    `vendors` ON `vendors`.`id` = `transactions`.`vendor_id`
LEFT JOIN
    `refunds` ON `refunds`.`transaction_id` = `transactions`.`id`
LEFT JOIN
    `groups` ON `groups`.`id` IN
    ( 
        SELECT `group_id` FROM `properties` WHERE `id` IN
        ( 
            SELECT `property_id` FROM `vendor_properties`
            WHERE `vendor_id` = @refID
        )
     );

Вывод:

+------------+-----------+------------+-------+--------+----------+--------+
| DB_transID | DB_vendID | VendorCode | Order | Amount | Refunded | Group  |
+------------+-----------+------------+-------+--------+----------+--------+
| 1          | 12        | abc123     | 0032  | 25     | NULL     | groupA |
| 1          | 12        | abc123     | 0032  | 25     | NULL     | groupB |
| 2          | 13        | efg321     | 0063  | 50     | 10       | groupA |
| 3          | 14        | hjk456     | 0073  | 50     | NULL     | groupB |
| 4          | 15        | fed789     | 0087  | 50     | NULL     | NULL   |
+------------+-----------+------------+-------+--------+----------+--------+

Я бы хотел сделать следующее:

  1. Добавить столбец «Нетто», содержащий значение (Сумма - Возврат)
  2. Когда транзакция имеет более одной группы, как в транзакции 1, вместо создания двух строк я бы хотел одну строку с «groupA, groupB» в столбце Group. И когда Group имеет значение NULL, значение должно быть «None». Список имен групп должен быть дедуплицирован. Например, если группа «А» появляется в трех транзакциях, а группа «Б» - в двух транзакциях, результатом будет «группа А, группа В».
  3. Когда Refunded равен NULL, значение должно быть «0»

Таким образом, желаемый результат будет:

+------------+-----------+------------+-------+--------+----------+-----+----------------+
| DB_transID | DB_vendID | VendorCode | Order | Amount | Refunded | Net | Group          |
+------------+-----------+------------+-------+--------+----------+-----+----------------+
| 1          | 12        | abc123     | 0032  | 25     | 0        | 25  | groupA, groupB |
| 2          | 13        | efg321     | 0063  | 50     | 10       | 40  | groupA         |
| 3          | 14        | hjk456     | 0073  | 50     | 0        | 50  | groupB         |
| 4          | 15        | fed789     | 0087  | 50     | 0        | 50  | None           |
+------------+-----------+------------+-------+--------+----------+-----+----------------+

В реальной жизни в большинстве этих таблиц есть несколько тысяч строк. В качестве дополнительного вопроса, скажите мне, почему я иногда получаю NULL для группы, даже если данные таковы, что должно быть значение?

Любые дополнительные улучшения в запросе приветствуются!

1 Ответ

0 голосов
/ 03 ноября 2018

Это мой первый подход к вашим целям, я буду обновлять, если я обнаружил какие-либо улучшения:

SELECT
    t.id AS DB_transID,
    t.vendor_id AS DB_vendID,
    t.amount AS Amount,
    v.vendor_code AS VendorCode,
    p.order AS "Order",
    IFNULL(r.amount, 0) AS Refunded,
    IFNULL(t.amount, 0) - IFNULL(r.amount, 0) AS Net,
    IFNULL((
     SELECT GROUP_CONCAT(DISTINCT g.name SEPARATOR ', ')
     FROM vendor_properties vp
     LEFT JOIN properties pr ON pr.id = vp.property_id
     LEFT JOIN groups g ON g.id = pr.group_id
     WHERE vp.vendor_id = t.vendor_id
     GROUP BY vp.vendor_id
    ), "None") AS "Groups"
FROM
    transactions t
LEFT JOIN
     payments p ON p.id = t.payment_id
LEFT JOIN
     vendors v ON v.id = t.vendor_id
LEFT JOIN
     refunds r ON r.transaction_id = t.id;

Улучшение по сравнению с предыдущим запросом будет следующим: даже если некоторые из ваших внешних ключей не допускают значений NULL, тогда LEFT JOIN между связанными таблицами можно выполнить с помощью INNER JOIN:

SELECT
    t.id AS DB_transID,
    ANY_VALUE(t.vendor_id) AS DB_vendID,
    ANY_VALUE(t.amount) AS Amount,
    ANY_VALUE(v.vendor_code) AS VendorCode,
    ANY_VALUE(p.order) AS "Order",
    IFNULL(ANY_VALUE(r.amount), 0) AS Refunded,
    IFNULL(ANY_VALUE(t.amount), 0) - IFNULL(ANY_VALUE(r.amount), 0) AS Net,
    IFNULL(GROUP_CONCAT(DISTINCT g.name SEPARATOR ', '), "None") AS "Group"
FROM
    transactions t
LEFT JOIN
    payments p ON p.id = t.payment_id
LEFT JOIN
    vendors v ON v.id = t.vendor_id
LEFT JOIN
    refunds r ON r.transaction_id = t.id
LEFT JOIN
    vendor_properties vp ON vp.vendor_id = t.vendor_id
LEFT JOIN
    properties pr ON pr.id = vp.property_id
LEFT JOIN
    groups g ON g.id = pr.group_id
GROUP BY
    t.id

Надеюсь, это вам поможет, вы можете поиграть с рабочим примером здесь:

DB-Fiddle

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...