powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Хитрая сортировка
25 сообщений из 34, страница 1 из 2
Хитрая сортировка
    #39357765
_hz_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ну может и не сортировка...
В общем, суть задачи:
Есть таблица клиент--плательщик--месяц_выплаты--сумма_выплаты. Надо для каждого клиента определить плательщика от которого он получил последнюю выплату. Если суммы за последний месяц равны, то сравниваются суммы за предыдущий и т.д.
Количество плательщиков может быть любое. Выплаты не обязательно производятся каждый месяц.

Пример исходных данных:
CLIENTPAYERPAY_MONTHPAY_SUMAQ330AW330AQ220AW220AW115AQ110BE225BR150BR110CT340CY340CY160CT130
Искомый результат:
CLIENTPAYERAWBECY

Пробовал такую конструкцию
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
SELECT
     Client
    ,Payer
FROM (
        SELECT
             Client
            ,Payer
            ,Pay_Month
            ,Pay_Sum
            ,ROW_NUMBER() OVER (
                    PARTITION BY Client
                    ORDER BY Pay_Month DESC, Pay_Sum DESC
                ) AS Rn
        FROM Tab
    ) T
WHERE Rn = 1


Результат не тот
CLIENTPAYERAQBECT

У кого какие мысли?
Хочется сделать элегантно, без десятка вложенных запросов или переборов в цикле. Всю голову уже сломал.
...
Рейтинг: 0 / 0
Хитрая сортировка
    #39357772
Lary Denis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_hz_Если суммы за последний месяц равны, то сравниваются суммы за предыдущий и т.д.

Какие именно суммы? Что с чем сравнивается?


хорошо бы еще и запрос с кляузой with из dual.
...
Рейтинг: 0 / 0
Хитрая сортировка
    #39357778
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_hz_Результат не тот


Результат не тот потому-чтo ты нe зaдaл правило что делать eсли сумма выплаты двух или более плательщиков за последний месяц равны. Хочешь плательщика с максимальным именем - добавь Payer DESC в ORDER BY.

SY.
...
Рейтинг: 0 / 0
Хитрая сортировка
    #39357789
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_hz_Есть таблица клиент--плательщик--месяц_выплаты--сумма_выплаты.
Надо для каждого клиента определить плательщика от которого он получил последнюю выплату.
Если суммы за последний месяц равны , то сравниваются суммы за предыдущий и т.д.
Объясните нам свою логику, что Вы имели ввиду.
Пока это - в огороде бузина, а в Киеве дядька.
Зачем Вам вообще равенство сумм. А если не равенство, что делать? И равенство среди плательщиков по средней сумме (типа Вася 100, Петя 200, Дима 200, Олег 300) Вас интересует?
...
Рейтинг: 0 / 0
Хитрая сортировка
    #39357798
_hz_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Lary DenisКакие именно суммы? Что с чем сравнивается?Суммы выплат. Поле Pay_Sum.

SY Результат не тот потому-чтo ты нe зaдaл правило что делать eсли сумма выплаты двух или более плательщиков за последний месяц равны. Хочешь плательщика с максимальным именем - добавь Payer DESC в ORDER BY.
Нет, не хочу. В этом случае надо смотреть предыдущий месяц и сравнивать суммы выплат в нём.

Т.е. получается рекурсивный алгоритм:
1. Ищем максимальное значение Pay_Sum за максимальный Pay_Month. Если оно одно, то значение Payer -- результат.
2. Если максимальное значение Pay_Sum несколько, то выполняем шаг 1 для Pay_Month - 1.

по просьбам трудящихся запрос с исходными данными
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
WITH Tab AS (
        SELECT 'A' AS Client, 'Q' AS Payer, 1 AS Pay_Month, 10 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'A' AS Client, 'W' AS Payer, 1 AS Pay_Month, 15 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'A' AS Client, 'Q' AS Payer, 2 AS Pay_Month, 20 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'A' AS Client, 'W' AS Payer, 2 AS Pay_Month, 20 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'A' AS Client, 'Q' AS Payer, 3 AS Pay_Month, 30 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'A' AS Client, 'W' AS Payer, 3 AS Pay_Month, 30 AS Pay_Sum FROM Dual
        
        UNION ALL
        SELECT 'B' AS Client, 'R' AS Payer, 1 AS Pay_Month, 10 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'B' AS Client, 'R' AS Payer, 1 AS Pay_Month, 50 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'B' AS Client, 'E' AS Payer, 2 AS Pay_Month, 25 AS Pay_Sum FROM Dual

        UNION ALL
        SELECT 'C' AS Client, 'T' AS Payer, 1 AS Pay_Month, 30 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'C' AS Client, 'Y' AS Payer, 1 AS Pay_Month, 60 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'C' AS Client, 'T' AS Payer, 3 AS Pay_Month, 40 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'C' AS Client, 'Y' AS Payer, 3 AS Pay_Month, 40 AS Pay_Sum FROM Dual
    )
    SELECT
         Client
        ,Payer
        ,Pay_Month
        ,Pay_Sum
    FROM Tab

...
Рейтинг: 0 / 0
Хитрая сортировка
    #39357810
_hz_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сергей Арсеньев,

Прошу прощенья, недостаточно описал задачу.

Есть таблица клиент(Client)--плательщик(Payer)--месяц_выплаты(Pay_Month)--сумма_выплаты(Pay_Sum). Надо для каждого клиента определить плательщика от которого он получил последнюю (с наибольшим значением Pay_Month) выплату. Если за этот месяц выплат несколько, берём с наибольшей суммой выплаты (Pay_Sum). Если суммы (значения Pay_Sum) за последний месяц равны, то сравниваются суммы (значения Pay_Sum) за предыдущий месяц и т.д.
Количество плательщиков может быть любое. Выплаты не обязательно производятся каждый месяц.


Сергей Арсеньев И равенство среди плательщиков по средней сумме (типа Вася 100, Петя 200, Дима 200, Олег 300) Вас интересует?Если всё было бы так просто...)
...
Рейтинг: 0 / 0
Хитрая сортировка
    #39357814
Glays
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_hz_, некрасиво, но без рекурсии
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
WITH Tab
     AS (SELECT 'A' AS Client, 'Q' AS Payer, 1 AS Pay_Month, 10 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'A' AS Client, 'W' AS Payer, 1 AS Pay_Month, 15 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'A' AS Client, 'Q' AS Payer, 2 AS Pay_Month, 20 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'A' AS Client, 'W' AS Payer, 2 AS Pay_Month, 20 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'A' AS Client, 'Q' AS Payer, 3 AS Pay_Month, 30 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'A' AS Client, 'W' AS Payer, 3 AS Pay_Month, 30 AS Pay_Sum FROM Dual
        
        UNION ALL
        SELECT 'B' AS Client, 'R' AS Payer, 1 AS Pay_Month, 10 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'B' AS Client, 'R' AS Payer, 1 AS Pay_Month, 50 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'B' AS Client, 'E' AS Payer, 2 AS Pay_Month, 25 AS Pay_Sum FROM Dual

        UNION ALL
        SELECT 'C' AS Client, 'T' AS Payer, 1 AS Pay_Month, 30 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'C' AS Client, 'Y' AS Payer, 1 AS Pay_Month, 60 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'C' AS Client, 'T' AS Payer, 3 AS Pay_Month, 40 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'C' AS Client, 'Y' AS Payer, 3 AS Pay_Month, 40 AS Pay_Sum FROM Dual),
     prepare_tab
     AS (  SELECT CLIENT,
                  PAYER,
                  PAY_MONTH,
                  SUM (PAY_SUM) AS PAY_SUM
             FROM Tab
         GROUP BY CLIENT, PAYER, PAY_MONTH),
     all_monthsXclients
     AS (SELECT PAY_MONTH, CLIENT, PAYER
           FROM (SELECT DISTINCT PAY_MONTH
                   FROM Tab),
                (SELECT DISTINCT CLIENT, PAYER
                   FROM Tab)),
     all_clients
     AS (SELECT DISTINCT PAY_MONTH
           FROM Tab)
SELECT Client, Payer
  FROM (SELECT Client,
               Payer,
               RANK () OVER (PARTITION BY Client ORDER BY PAY_MONTH DESC) r_n
          FROM (SELECT a.*,
                       COUNT (DISTINCT rn)
                          OVER (PARTITION BY Client, PAY_MONTH)
                          AS cnt,
                       MAX (Pay_Sum) OVER (PARTITION BY Client, PAY_MONTH)
                          AS max_pay
                  FROM (  SELECT a_m.Client,
                                 a_m.Payer,
                                 a_m.PAY_MONTH,
                                 Pay_Sum,
                                 RANK ()
                                 OVER (
                                    PARTITION BY a_m.Client
                                    ORDER BY a_m.Pay_Month DESC, Pay_Sum DESC)
                                    AS Rn
                            FROM all_monthsXclients a_m
                                 LEFT JOIN prepare_tab t
                                    ON     t.PAY_MONTH = a_m.PAY_MONTH
                                       AND t.Client = a_m.Client
                                       AND t.PAYER = a_m.PAYER
                        ORDER BY Client, Rn) a)
         WHERE cnt > 1 AND Pay_Sum = max_pay)
 WHERE r_n = 1

...
Рейтинг: 0 / 0
Хитрая сортировка
    #39357817
Фотография --Eugene--
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_hz_,

знаю, что неправильно, зато сходится
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
with x as (
select 'A' CLIENT, 'Q' PAYER, 3 PAY_MONTH, 30 PAY_SUM from dual
union all select 'A', 'W', 3, 30 from dual
union all select 'A', 'Q', 2, 20 from dual
union all select 'A', 'W', 2, 20 from dual
union all select 'A', 'W', 1, 15 from dual
union all select 'A', 'Q', 1, 10 from dual
union all select 'B', 'E', 2, 25 from dual
union all select 'B', 'R', 1, 50 from dual
union all select 'B', 'R', 1, 10 from dual
union all select 'C', 'T', 3, 40 from dual
union all select 'C', 'Y', 3, 40 from dual
union all select 'C', 'Y', 1, 60 from dual
union all select 'C', 'T', 1, 30 from dual
)
select client, max(payer) keep (dense_rank last order by pay_month, pay_sum) payer
    from x
    group by client

CLIENTPAYERAWBECY
...
Рейтинг: 0 / 0
Хитрая сортировка
    #39357821
Фотография AmKad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
WITH Tab AS (
        SELECT 'A' AS Client, 'Q' AS Payer, 1 AS Pay_Month, 10 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'A' AS Client, 'W' AS Payer, 1 AS Pay_Month, 15 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'A' AS Client, 'Q' AS Payer, 2 AS Pay_Month, 20 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'A' AS Client, 'W' AS Payer, 2 AS Pay_Month, 20 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'A' AS Client, 'Q' AS Payer, 3 AS Pay_Month, 30 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'A' AS Client, 'W' AS Payer, 3 AS Pay_Month, 30 AS Pay_Sum FROM Dual

        UNION ALL
        SELECT 'B' AS Client, 'R' AS Payer, 1 AS Pay_Month, 10 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'B' AS Client, 'R' AS Payer, 1 AS Pay_Month, 50 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'B' AS Client, 'E' AS Payer, 2 AS Pay_Month, 25 AS Pay_Sum FROM Dual

        UNION ALL
        SELECT 'C' AS Client, 'T' AS Payer, 1 AS Pay_Month, 30 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'C' AS Client, 'Y' AS Payer, 1 AS Pay_Month, 60 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'C' AS Client, 'T' AS Payer, 3 AS Pay_Month, 40 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'C' AS Client, 'Y' AS Payer, 3 AS Pay_Month, 40 AS Pay_Sum FROM Dual
    )
select client, max(payer) keep (dense_rank last order by pay_month) payer
from
   (select client, payer, pay_month, pay_sum,
    row_number()  over (partition by client, pay_month          order by pay_sum desc) dr,
    count     (*) over (partition by client, pay_month, pay_sum order by pay_sum     ) cnt
    from tab
   )
where dr = cnt and cnt = 1
group by client;

C P
- -
A W
B E
C Y

...
Рейтинг: 0 / 0
Хитрая сортировка
    #39357822
Glays
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
--Eugene--, а я не решился такой ответ постить.
...
Рейтинг: 0 / 0
Хитрая сортировка
    #39357825
Фотография AmKad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AmKad
Код: plsql
1.
    count     (*) over (partition by client, pay_month, pay_sum order by pay_sum     ) cnt   

Без выделенного можно обойтись. Ошибка копипаста.
...
Рейтинг: 0 / 0
Хитрая сортировка
    #39357845
_hz_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
--Eugene--_hz_,

знаю, что неправильно, зато сходится
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
with x as (
select 'A' CLIENT, 'Q' PAYER, 3 PAY_MONTH, 30 PAY_SUM from dual
union all select 'A', 'W', 3, 30 from dual
union all select 'A', 'Q', 2, 20 from dual
union all select 'A', 'W', 2, 20 from dual
union all select 'A', 'W', 1, 15 from dual
union all select 'A', 'Q', 1, 10 from dual
union all select 'B', 'E', 2, 25 from dual
union all select 'B', 'R', 1, 50 from dual
union all select 'B', 'R', 1, 10 from dual
union all select 'C', 'T', 3, 40 from dual
union all select 'C', 'Y', 3, 40 from dual
union all select 'C', 'Y', 1, 60 from dual
union all select 'C', 'T', 1, 30 from dual
)
select client, max(payer) keep (dense_rank last order by pay_month, pay_sum) payer
    from x
    group by client

CLIENTPAYERAWBECY


Это только в примере так получилось, что Payer-ы по алфавиту)
...
Рейтинг: 0 / 0
Хитрая сортировка
    #39357851
_hz_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Glays_hz_, некрасиво, но без рекурсии
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
WITH Tab
     AS (SELECT 'A' AS Client, 'Q' AS Payer, 1 AS Pay_Month, 10 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'A' AS Client, 'W' AS Payer, 1 AS Pay_Month, 15 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'A' AS Client, 'Q' AS Payer, 2 AS Pay_Month, 20 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'A' AS Client, 'W' AS Payer, 2 AS Pay_Month, 20 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'A' AS Client, 'Q' AS Payer, 3 AS Pay_Month, 30 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'A' AS Client, 'W' AS Payer, 3 AS Pay_Month, 30 AS Pay_Sum FROM Dual
        
        UNION ALL
        SELECT 'B' AS Client, 'R' AS Payer, 1 AS Pay_Month, 10 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'B' AS Client, 'R' AS Payer, 1 AS Pay_Month, 50 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'B' AS Client, 'E' AS Payer, 2 AS Pay_Month, 25 AS Pay_Sum FROM Dual

        UNION ALL
        SELECT 'C' AS Client, 'T' AS Payer, 1 AS Pay_Month, 30 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'C' AS Client, 'Y' AS Payer, 1 AS Pay_Month, 60 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'C' AS Client, 'T' AS Payer, 3 AS Pay_Month, 40 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'C' AS Client, 'Y' AS Payer, 3 AS Pay_Month, 40 AS Pay_Sum FROM Dual),
     prepare_tab
     AS (  SELECT CLIENT,
                  PAYER,
                  PAY_MONTH,
                  SUM (PAY_SUM) AS PAY_SUM
             FROM Tab
         GROUP BY CLIENT, PAYER, PAY_MONTH),
     all_monthsXclients
     AS (SELECT PAY_MONTH, CLIENT, PAYER
           FROM (SELECT DISTINCT PAY_MONTH
                   FROM Tab),
                (SELECT DISTINCT CLIENT, PAYER
                   FROM Tab)),
     all_clients
     AS (SELECT DISTINCT PAY_MONTH
           FROM Tab)
SELECT Client, Payer
  FROM (SELECT Client,
               Payer,
               RANK () OVER (PARTITION BY Client ORDER BY PAY_MONTH DESC) r_n
          FROM (SELECT a.*,
                       COUNT (DISTINCT rn)
                          OVER (PARTITION BY Client, PAY_MONTH)
                          AS cnt,
                       MAX (Pay_Sum) OVER (PARTITION BY Client, PAY_MONTH)
                          AS max_pay
                  FROM (  SELECT a_m.Client,
                                 a_m.Payer,
                                 a_m.PAY_MONTH,
                                 Pay_Sum,
                                 RANK ()
                                 OVER (
                                    PARTITION BY a_m.Client
                                    ORDER BY a_m.Pay_Month DESC, Pay_Sum DESC)
                                    AS Rn
                            FROM all_monthsXclients a_m
                                 LEFT JOIN prepare_tab t
                                    ON     t.PAY_MONTH = a_m.PAY_MONTH
                                       AND t.Client = a_m.Client
                                       AND t.PAYER = a_m.PAYER
                        ORDER BY Client, Rn) a)
         WHERE cnt > 1 AND Pay_Sum = max_pay)
 WHERE r_n = 1



Боюсь, на боевых объёмах сервер ниасилит
...
Рейтинг: 0 / 0
Хитрая сортировка
    #39357862
mraks
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
AmKad,

ваш запрос не предусматривает такие случаи

SELECT 'A' AS Client, 'Q' AS Payer, 1 AS Pay_Month, 10 AS Pay_Sum FROM Dual
UNION ALL
SELECT 'A' AS Client, 'W' AS Payer, 1 AS Pay_Month, 10 AS Pay_Sum FROM Dual

тут, наверно, нужно брать любого payer, ваш запрос не вернет никакого
...
Рейтинг: 0 / 0
Хитрая сортировка
    #39357863
_hz_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
AmKad
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
WITH Tab AS (
        SELECT 'A' AS Client, 'Q' AS Payer, 1 AS Pay_Month, 10 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'A' AS Client, 'W' AS Payer, 1 AS Pay_Month, 15 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'A' AS Client, 'Q' AS Payer, 2 AS Pay_Month, 20 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'A' AS Client, 'W' AS Payer, 2 AS Pay_Month, 20 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'A' AS Client, 'Q' AS Payer, 3 AS Pay_Month, 30 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'A' AS Client, 'W' AS Payer, 3 AS Pay_Month, 30 AS Pay_Sum FROM Dual

        UNION ALL
        SELECT 'B' AS Client, 'R' AS Payer, 1 AS Pay_Month, 10 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'B' AS Client, 'R' AS Payer, 1 AS Pay_Month, 50 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'B' AS Client, 'E' AS Payer, 2 AS Pay_Month, 25 AS Pay_Sum FROM Dual

        UNION ALL
        SELECT 'C' AS Client, 'T' AS Payer, 1 AS Pay_Month, 30 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'C' AS Client, 'Y' AS Payer, 1 AS Pay_Month, 60 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'C' AS Client, 'T' AS Payer, 3 AS Pay_Month, 40 AS Pay_Sum FROM Dual
        UNION ALL
        SELECT 'C' AS Client, 'Y' AS Payer, 3 AS Pay_Month, 40 AS Pay_Sum FROM Dual
    )
select client, max(payer) keep (dense_rank last order by pay_month) payer
from
   (select client, payer, pay_month, pay_sum,
    row_number()  over (partition by client, pay_month          order by pay_sum desc) dr,
    count     (*) over (partition by client, pay_month, pay_sum order by pay_sum     ) cnt
    from tab
   )
where dr = cnt and cnt = 1
group by client;

C P
- -
A W
B E
C Y



А это надо обдумать
...
Рейтинг: 0 / 0
Хитрая сортировка
    #39357869
mraks
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
AmKad,
А еще, я, возможно неправильно понял условие, но на этих данных, запрос вернет E, а надо Q.
Хотя это условие можно уточнить: после того, как в максимальный день совпали суммы для двух payer мы будем сравнивать предыдущие дни только для них или для всех?
Какой результат должен получиться на примере ниже?

WITH Tab AS (
SELECT 'A' AS Client, 'Q' AS Payer, 1 AS Pay_Month, 10 AS Pay_Sum FROM Dual
UNION ALL
SELECT 'A' AS Client, 'E' AS Payer, 1 AS Pay_Month, 15 AS Pay_Sum FROM Dual
UNION ALL
SELECT 'A' AS Client, 'Q' AS Payer, 2 AS Pay_Month, 20 AS Pay_Sum FROM Dual
UNION ALL
SELECT 'A' AS Client, 'W' AS Payer, 2 AS Pay_Month, 20 AS Pay_Sum FROM Dual
)
select client, max(payer) keep (dense_rank last order by pay_month) payer
from
(select client, payer, pay_month, pay_sum,
row_number() over (partition by client, pay_month order by pay_sum desc) dr,
count (*) over (partition by client, pay_month, pay_sum order by pay_sum ) cnt
from tab
)
where dr = cnt and cnt = 1
group by client;
...
Рейтинг: 0 / 0
Хитрая сортировка
    #39357870
Фотография AmKad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mraksSELECT 'A' AS Client, 'Q' AS Payer, 1 AS Pay_Month, 10 AS Pay_Sum FROM Dual
UNION ALL
SELECT 'A' AS Client, 'W' AS Payer, 1 AS Pay_Month, 10 AS Pay_Sum FROM Dual
Да, я намеренно не стал учитывать такие случаи, потому что ты поленился описать логику их обработки в своей недопостановке задачи. Значит допилишь сам.
...
Рейтинг: 0 / 0
Хитрая сортировка
    #39357874
mraks
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
AmKad,

я не автор задачи, я не поленился придумать исключение для твоей реализации
...
Рейтинг: 0 / 0
Хитрая сортировка
    #39357876
Фотография AmKad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mraks,

Тогда считай, что то сообщение адресовано топикстартеру
...
Рейтинг: 0 / 0
Хитрая сортировка
    #39357882
Фотография AmKad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mraksА еще, я, возможно неправильно понял условие, но на этих данных, запрос вернет E, а надо Q.
Хотя это условие можно уточнить: после того, как в максимальный день совпали суммы для двух payer мы будем сравнивать предыдущие дни только для них или для всех?
group by client;

Да, мне кажется твоя трактовка отличается от того, что хотел автор.
_hz_Надо для каждого клиента определить плательщика от которого он получил последнюю выплату. Если суммы за последний месяц равны, то сравниваются суммы за предыдущий и т.д.
...
Рейтинг: 0 / 0
Хитрая сортировка
    #39357895
Фотография --Eugene--
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_hz_,

вроде, правильно
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
with x as (
select 'A' CLIENT, 'Q' PAYER, 3 PAY_MONTH, 30 PAY_SUM from dual
union all select 'A', 'W', 3, 30 from dual
union all select 'A', 'Q', 2, 20 from dual
union all select 'A', 'W', 2, 20 from dual
union all select 'A', 'W', 1, 15 from dual
union all select 'A', 'Q', 1, 10 from dual
union all select 'B', 'E', 2, 25 from dual
union all select 'B', 'R', 1, 50 from dual
union all select 'B', 'R', 1, 10 from dual
union all select 'C', 'T', 3, 40 from dual
union all select 'C', 'Y', 3, 40 from dual
union all select 'C', 'Y', 1, 60 from dual
union all select 'C', 'T', 1, 30 from dual
),
y as (
    select client,
            pay_month,
            min(payer) keep (dense_rank last order by pay_sum) as payer
        from x
        group by client,
            pay_month
        having count(1) keep (dense_rank last order by pay_sum) = 1
)
select client,
        min(payer) as payer
    from y
    group by client

CLIENT;PAYERA;WB;EC;Y
...
Рейтинг: 0 / 0
Хитрая сортировка
    #39357905
Фотография --Eugene--
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
нет, неправильно :(
...
Рейтинг: 0 / 0
Хитрая сортировка
    #39357915
Фотография --Eugene--
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вот так правильно
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
with x as (
select 'A' CLIENT, 'Q' PAYER, 3 PAY_MONTH, 30 PAY_SUM from dual
union all select 'A', 'W', 3, 30 from dual
union all select 'A', 'Q', 2, 20 from dual
union all select 'A', 'W', 2, 20 from dual
union all select 'A', 'W', 1, 15 from dual
union all select 'A', 'Q', 1, 10 from dual
union all select 'B', 'E', 2, 25 from dual
union all select 'B', 'R', 1, 50 from dual
union all select 'B', 'R', 1, 10 from dual
union all select 'C', 'T', 3, 40 from dual
union all select 'C', 'Y', 3, 40 from dual
union all select 'C', 'Y', 1, 60 from dual
union all select 'C', 'T', 1, 30 from dual
),
y as (
    select client,
            pay_month,
            min(payer) keep (dense_rank last order by pay_sum) as payer,
            min(pay_sum) keep (dense_rank last order by pay_sum) as pay_sum
        from x
        group by client,
            pay_month
        having count(1) keep (dense_rank last order by pay_sum) = 1
)
select client,
        min(payer) keep (dense_rank last order by pay_month, pay_sum) as payer
    from y
    group by client

...
Рейтинг: 0 / 0
Хитрая сортировка
    #39357937
Фотография --Eugene--
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AmKadmraksSELECT 'A' AS Client, 'Q' AS Payer, 1 AS Pay_Month, 10 AS Pay_Sum FROM Dual
UNION ALL
SELECT 'A' AS Client, 'W' AS Payer, 1 AS Pay_Month, 10 AS Pay_Sum FROM Dual
Да, я намеренно не стал учитывать такие случаи, потому что ты поленился описать логику их обработки в своей недопостановке задачи. Значит допилишь сам.
Тебе же сказано:
_hz_...
Если суммы за последний месяц равны, то сравниваются суммы за предыдущий и т.д.
...

значит, если в месяце есть более одной одинаковой у разных PAYER-ов, - этот месяц не учитывается.
...
Рейтинг: 0 / 0
Хитрая сортировка
    #39357948
Фотография AmKad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
--Eugene--Тебе же сказано
Так-то оно так, но не сказано, что если текущий месяц - первый, и сравнивать за предыдущий нечего.
...
Рейтинг: 0 / 0
25 сообщений из 34, страница 1 из 2
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Хитрая сортировка
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]