Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Хитрая сортировка / 25 сообщений из 34, страница 1 из 2
30.11.2016, 15:59
    #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
30.11.2016, 16:07
    #39357772
Lary Denis
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая сортировка
_hz_Если суммы за последний месяц равны, то сравниваются суммы за предыдущий и т.д.

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


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


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

SY.
...
Рейтинг: 0 / 0
30.11.2016, 16:30
    #39357789
Сергей Арсеньев
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая сортировка
_hz_Есть таблица клиент--плательщик--месяц_выплаты--сумма_выплаты.
Надо для каждого клиента определить плательщика от которого он получил последнюю выплату.
Если суммы за последний месяц равны , то сравниваются суммы за предыдущий и т.д.
Объясните нам свою логику, что Вы имели ввиду.
Пока это - в огороде бузина, а в Киеве дядька.
Зачем Вам вообще равенство сумм. А если не равенство, что делать? И равенство среди плательщиков по средней сумме (типа Вася 100, Петя 200, Дима 200, Олег 300) Вас интересует?
...
Рейтинг: 0 / 0
30.11.2016, 16:41
    #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
30.11.2016, 16:54
    #39357810
_hz_
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая сортировка
Сергей Арсеньев,

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

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


Сергей Арсеньев И равенство среди плательщиков по средней сумме (типа Вася 100, Петя 200, Дима 200, Олег 300) Вас интересует?Если всё было бы так просто...)
...
Рейтинг: 0 / 0
30.11.2016, 16:58
    #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
30.11.2016, 16:59
    #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
30.11.2016, 17:03
    #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
30.11.2016, 17:03
    #39357822
Glays
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая сортировка
--Eugene--, а я не решился такой ответ постить.
...
Рейтинг: 0 / 0
30.11.2016, 17:05
    #39357825
AmKad
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая сортировка
AmKad
Код: plsql
1.
    count     (*) over (partition by client, pay_month, pay_sum order by pay_sum     ) cnt   

Без выделенного можно обойтись. Ошибка копипаста.
...
Рейтинг: 0 / 0
30.11.2016, 17:27
    #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
30.11.2016, 17:31
    #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
30.11.2016, 17:43
    #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
30.11.2016, 17:43
    #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
30.11.2016, 17:47
    #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
30.11.2016, 17:49
    #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
30.11.2016, 17:50
    #39357874
mraks
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая сортировка
AmKad,

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

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

Да, мне кажется твоя трактовка отличается от того, что хотел автор.
_hz_Надо для каждого клиента определить плательщика от которого он получил последнюю выплату. Если суммы за последний месяц равны, то сравниваются суммы за предыдущий и т.д.
...
Рейтинг: 0 / 0
30.11.2016, 18:10
    #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
30.11.2016, 18:18
    #39357905
--Eugene--
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая сортировка
нет, неправильно :(
...
Рейтинг: 0 / 0
30.11.2016, 18:23
    #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
30.11.2016, 18:35
    #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
30.11.2016, 18:41
    #39357948
AmKad
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Хитрая сортировка
--Eugene--Тебе же сказано
Так-то оно так, но не сказано, что если текущий месяц - первый, и сравнивать за предыдущий нечего.
...
Рейтинг: 0 / 0
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Хитрая сортировка / 25 сообщений из 34, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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