За последние 24 часа нас посетили 19993 программиста и 1695 роботов. Сейчас ищет 1881 программист ...

Группировка строк при присоединении 2-х таблиц

Тема в разделе "MySQL", создана пользователем Matpewka, 30 авг 2017.

  1. Matpewka

    Matpewka Новичок

    С нами с:
    3 мар 2017
    Сообщения:
    6
    Симпатии:
    2
    Проблема:
    В результирующем выводе при LEFT JOIN количество строк, в тех таблицах в которых строк меньше, будет увеличено до наибольшего количества строк.

    Поясню.

    Есть 3 таблицы:
    1. user: id - пользователи
    2. invoice: user_id, amount - списание баланса
    3. transaction: user_id, amount - списание и пополнение баланса
    Задача: выбрать пользователей с положительным балансом.
    Делаю это запросом:
    Код (Text):
    1. SELECT user.id, sum(transaction.amount) - sum(invoice.amount) as balance
    2. FROM user
    3. LEFT JOIN invoice ON invoice.user_id = user.id
    4. LEFT JOIN transaction ON transaction.customer_id = user.id
    5. GROUP BY user.id
    6. HAVING balance >0
    Допустим есть следующие исходные данные:
    user:
    1

    invoice:
    user_id | amount
    1 | 50

    transaction:
    customer_id | amount
    1 | -10
    1 | 50
    1 | 60

    В результате запроса таблица invoice приджойнится 3 раза, что приводит к тому что у пользователя списание баланса будет не 50, а 150.

    Аналогичная ситуация может быть и когда в инвойсах больше строк чем в транзакциях.

    Сейчас вижу возможность сделать это 2-мя запросами:
    Код (Text):
    1. SELECT user.id, -1 * sum(invoice.amount) as balance
    2. FROM user
    3. LEFT JOIN invoice ON invoice.user_id = user.id
    4. GROUP BY user.id
    Код (Text):
    1. SELECT user.id, sum(transaction.amount)  as balance
    2. FROM user
    3. LEFT JOIN transaction ON transaction.customer_id = user.id
    4. GROUP BY user.id
    сделать по ним UNION и дальше работать с результатом.

    Выглядит ужасно криво. По сему прошу совета.
    Единственное ограничение - нет возможности изменить структуру таблиц.
     
  2. t1grok

    t1grok Новичок

    С нами с:
    29 янв 2017
    Сообщения:
    119
    Симпатии:
    32
    Пфф..ну так и делайте, через UNION.
    Еще можно сделать через коррелированные подзапросы, но это еще то уродство.
     
  3. Matpewka

    Matpewka Новичок

    С нами с:
    3 мар 2017
    Сообщения:
    6
    Симпатии:
    2
    Хочется чтобы было по феншую.
    Если других вариантов не будет, то сделаю через UNION
     
  4. retvizan

    retvizan Активный пользователь

    С нами с:
    27 дек 2013
    Сообщения:
    68
    Симпатии:
    22
    SELECT user.id, ifnull(q1,0) - ifnull(q2,0) as balance
    FROM user
    LEFT JOIN (select user_id, sum(invoice.amount) as q1 from invoice group by user_id) t1 ON t1.user_id = user.id
    LEFT JOIN (select customer_id, sum(transaction.amount) as q2 from transaction group by customer_id) t2 ON t2.customer_id = user.id
    where ifnull(q1,0) - ifnull(q2,0) > 0;
     
    Matpewka нравится это.
  5. Matpewka

    Matpewka Новичок

    С нами с:
    3 мар 2017
    Сообщения:
    6
    Симпатии:
    2
    Здорово, вечно про ifnull забываю, премного благодарю!