MySQL удаляет повторяющиеся отдельные значения

Интересно, можно ли удалить результаты с тем же значением?

У меня есть таблица платежей, содержащая КОРРЕКТИРОВКИ и ВОЗВРАТЫ, введенные как AJUSTE и ESTORNO. Хотя оба могут существовать в счете, если общая сумма каждого из них равна, их следует игнорировать. Если суммы каждого из них не равны, то они будут учитываться при расчете.

Я составил список каждого из них следующим образом:

select sum(pay_amount) as pay_amount, pay_type, pay_date, active, invoice_no, invoice_date 
from payments 
where pay_type = 'AJUSTE' 
    and pay_date like '%-%-2024' 
    and active = '1' 
    and pay_amount not in (
        select SUM(pay_amount) as pay_amount 
        from payments 
        where pay_type = 'ESTORNO' and pay_date like '%-%-2024' and active = '1' 
        group by invoice_no
    ) 
GROUP BY invoice_no;

Тогда этот запрос на противоположное:

select sum(pay_amount) as pay_amount, pay_type, pay_date, active, invoice_no, invoice_date 
from payments 
where pay_type = 'ESTORNO' 
    and pay_date like '%-%-2024' 
    and active = '1' 
    and pay_amount not in (
        select SUM(pay_amount) as pay_amount 
        from payments 
        where pay_type = 'AJUSTE' and pay_date like '%-%-2024' and active = '1' 
        group by invoice_no
    ) 
GROUP BY invoice_no;

Несмотря на то, что возвраты являются отрицательными, я хочу исключить все одинаковые суммы и добавить разные.

Возможно ли это с помощью запроса в MySQL 5.7?

---- редактировать ------

Я создал скрипт с демонстрационными данными: https://www.mycompiler.io/view/6qxcOxSlkuv

AJUSTE (Корректировки) — это положительные числа в БД, тогда как ESTORNO (возвраты) — это отрицательные суммы.

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

Также возможно, что корректировок может быть 2, а возврат только 1. Бывший. Клиент оплатил половину остатка, и эта половина платежа была возмещена, а также полная корректировка списания счета.

Запрос должен рассматривать каждый отдельный счет-фактуру. Когда сумма всех возвратов и корректировок в одном счете существует и равна нулю, мы пропускаем этот конкретный счет. Если сумма корректировки превышает сумму возврата или наоборот, нам нужен pay_type (AJUSTE или ESTORNO) с разницей (pay_type). (например, ESTORNO 100, AJUSTE 500. Должен вывести AJUSTE 400).

Запрос, указанный в ответе, возвращает счета-фактуры 78 и 79. В счете-фактуре 79 указано ESTORNO 100 и AJUSTE 551,20, что верно. В счете-фактуре 78 указано ESTORNO 100 и AJUSTE 200, что тоже верно.

В счете-фактуре 55 указано значение AJUSTE 2000, и он не отображается в результатах.

Надеюсь, все это имеет смысл.

--- второе редактирование -----

Если sum() AJUSTE и ESTORNO в bill_no одинакова, она игнорируется и не включается в результаты.

Если sum() AJUSTE или ESTORNO в инвойсе_no отличается, отобразите оба результата как положительное число.

Payment_id — это первичный ключ. Приношу извинения, поскольку в скрипте mysql его нет.

Ожидаемый результат от скрипта MySQL:

Обратите внимание, что в предложении WHEREpay_amount относится к значениям в таблице, а не SUM(pay_amount) AS pay_amount. Чтобы отфильтровать агрегированное значение, вам необходимо поставить условие HAVING.

Barmar 03.09.2024 21:40

спасибо за информацию Бармар. Можете ли вы показать мне пример, как это будет выглядеть?

Ronaldo 03.09.2024 21:48
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
0
2
61
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Объедините свои подзапросы и покажите только строки с разными суммами по одному и тому же счету.

SELECT e.*
FROM (
    select sum(pay_amount) as pay_amount, pay_type, invoice_no
    from payments 
    where pay_type = 'ESTORNO' and pay_date like '%-%-2024' and active = '1' 
    group by invoice_no, pay_type
) AS e
JOIN (
    select sum(pay_amount) as pay_amount, pay_type, invoice_no
    from payments 
    where pay_type = 'AJUSTE' and pay_date like '%-%-2024' and active = '1' 
    group by invoice_no, pay_type
) AS a ON a.invoice_no = e.invoice_no AND a.pay_amount != e.pay_amount

UNION ALL

SELECT a.*
FROM (
    select sum(pay_amount) as pay_amount, pay_type, invoice_no
    from payments 
    where pay_type = 'ESTORNO' and pay_date like '%-%-2024' and active = '1' 
    group by invoice_no, pay_type
) AS e
JOIN (
    select sum(pay_amount) as pay_amount, pay_type, invoice_no
    from payments 
    where pay_type = 'AJUSTE' and pay_date like '%-%-2024' and active = '1' 
    group by invoice_no, pay_type
) AS a ON a.invoice_no = e.invoice_no AND a.pay_amount != e.pay_amount

ДЕМО

Чтобы избежать ошибок ONLY_FULL_GROUP_BY, необходимо удалить столбцы pay_date, active и invoice_date из списка SELECT, поскольку они могут быть неуникальны внутри групп.

Я ценю пример Бармара, но я использую MySQL 5.7. Можно ли это сделать в 5.7?

Ronaldo 03.09.2024 22:47

Замените FROM e JOIN a на FROM (subquery) AS e JOIN (subquery) AS a, заменив subquery определениями каждого CTE.

Barmar 03.09.2024 22:50

Я ценю ваше время и усилия, но запрос не дал того, что я ищу. По сути, необходимо суммировать все AJUTES и все ESTORNO из каждого счета. Если сумма AJUSTE равна сумме ESTORNO по счету, ее следует игнорировать и в результате не возвращать.

Ronaldo 04.09.2024 20:54

Я думаю, вот что это делает. Он вычисляет отдельные суммы для AJUTES и ESTORNO в каждом подзапросе, а затем сравнивает суммы.

Barmar 04.09.2024 21:57

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

Barmar 04.09.2024 21:58

Привет, Бармар. Спасибо за внимание к этому вопросу. Я отредактировал вопрос, так как текст был слишком длинным, чтобы его можно было разместить здесь. Заранее спасибо!

Ronaldo 05.09.2024 15:09

Вам нужно отменить отдельные платежи и корректировки с одинаковыми суммами или только с общими суммами? Пожалуйста, отредактируйте вопрос, чтобы добавить ожидаемые результаты. Кроме того, вам необходимо сделать payment_id первичным ключом таблицы на mycompiler.io, иначе он получит ошибку от GROUP BY payment_id.

Barmar 05.09.2024 17:13

Привет, Бамар, я снова отредактировал вопрос. Моя рабочий пример не пометила pay_id как первичный ключ. В базе данных это первичный_ключ. извините за это.

Ronaldo 05.09.2024 17:31

Пожалуйста, не размещайте изображения, размещайте текст.

Barmar 05.09.2024 17:33

На самом деле, проблема с группировкой все еще существует. Мы группируем по invoice_no, а не по первичному ключу. В списке SELECT не может быть других неагрегированных столбцов, поскольку они могут иметь разные значения в разных строках группы.

Barmar 05.09.2024 17:36

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

Ronaldo 05.09.2024 17:40

Измените его на просто SELECT invoice_no, pay_type, SUM(pay_amount) AS pay_amount FROM ... GROUP BY invoice_no, pay_type. Избавьтесь от всех столбцов, поскольку они не будут уникальными.

Barmar 05.09.2024 17:42

Но в идеале вам следует нормализовать свои таблицы. Должна быть еще одна таблица счетов и invoice_no должен быть ФК.

Barmar 05.09.2024 17:43

Мне нужно было вернуть YEAR(pay_date) исходное LIKE состояние. Я не осознавал, что это VARCHAR, я предполагал, что это DATE.

Barmar 05.09.2024 17:51

Я сделал скрипку, показывающую результаты.

Barmar 05.09.2024 17:51

Давайте продолжим обсуждение в чате.

Ronaldo 05.09.2024 18:15
Ответ принят как подходящий

Посмотреть другой пример

Состояние When the sum of all refunds and adjustments within the same invoice exists and adds up to zero, we skip over that particular invoice.

Итак, первый шаг — расчет суммы для типа оплаты в («AJUSTE», «ESTORNO») для каждого номера счета-фактуры.
Берем счета, общая сумма которых не <>0.

Подзапрос.

select invoice_no
  ,sum(pay_amount) sum_AE
from payments p
where pay_type in('AJUSTE','ESTORNO') and pay_date like '%-%-2024' 
     and active = '1'
group by invoice_no
having abs(sum(pay_amount))>0.001
счет-фактура_нет сумма_AE 55 2000 г. 78 100 79 451.20000000000005

Полный запрос.
Внутреннее объединение предыдущего вывода с таблицей платежей

select p.invoice_no,abs(pay_amount) pay_amount,pay_type
from payments p
inner join(
   select invoice_no 
     ,sum(pay_amount) sum_AE
   from payments p
   where pay_type in('AJUSTE','ESTORNO') and pay_date like '%-%-2024' 
       and active = '1'
   group by invoice_no
   having abs(sum(pay_amount))>0.001
 )c on p.invoice_no=c.invoice_no
where pay_type in('AJUSTE','ESTORNO')
order by p.invoice_no ;
счет-фактура_нет pay_amount тип_платы 55 2000 г. НАСТРОЙКА 78 200 НАСТРОЙКА 78 100 ЭСТОРНО 79 551,2 НАСТРОЙКА 79 100 ЭСТОРНО

рабочий пример

Вау... ты сделал это. Спасибо!

Ronaldo 05.09.2024 19:59

Другие вопросы по теме