SQL получить первое не значение в зависимости от статуса - PullRequest
0 голосов
/ 09 июля 2020

Я не уверен, что заголовок правильный, но вот мой вопрос. У меня есть такая таблица:

+----+--------+--------------+---------+------------+
| id |  city  |   province   | status  |    date    |
+----+--------+--------------+---------+------------+
|  1 | cainta | rizal        | failed  | 01/01/2020 |
|  1 | null   | null         | success | 02/01/2020 |
|  1 | cainta | rizal        | failed  | 03/01/2020 |
|  2 | pasig  | metro manila | failed  | 04/01/2020 |
|  2 | pasig  | metro manila | failed  | 05/01/2020 |
|  2 | null   | null         | success | 06/01/2020 |
|  3 | obando | bulacan      | failed  | 07/01/2020 |
|  3 | null   | null         | failed  | 08/01/2020 |
|  3 | obando | bulacan      | success | 09/01/2020 |
+----+--------+--------------+---------+------------+

Теперь мне нужно получить все транзакции со статусом = 'success'. Если я это сделаю, результат будет примерно таким:

|   id | city   | province   | status   | date       |
|------|--------|------------|----------|------------|
|    1 | nan    | nan        | success  | 02/01/2020 |
|    2 | nan    | nan        | success  | 06/01/2020 |
|    3 | obando | bulacan    | success  | 09/01/2020 |

Мне нужно вот это:

|   id | city   | province     | status   | date       |
|------|--------|--------------|----------|------------|
|    1 | cainta | rizal        | success  | 02/01/2020 |
|    2 | pasig  | metro manila | success  | 06/01/2020 |
|    3 | obando | bulacan      | success  | 09/01/2020 |

Надеюсь, кто-то сможет пролить свет на то, как справиться с подобной ситуацией.

Ответы [ 4 ]

2 голосов
/ 09 июля 2020

Попробуйте следующее, используя lag()

with cte as
(
  select
      *,
      lag(city) over (order by id) as ncity,
      lag(province) over (order by id) as nprovince
  from myTable
)

select
    id,
    coalesce(city, ncity) as city,
    coalesce(province, nprovince) as province,
    status,
    date
from cte
where status = 'success';

вывод:

| id  | city   | province     | status  | date       |
| --- | ------ | ------------ | ------- | ---------- |
| 1   | cainta | rizal        | success | 02/01/2020 |
| 2   | pasig  | metro manila | success | 06/01/2020 |
| 3   | obando | bulacan      | success | 09/01/2020 |
1 голос
/ 09 июля 2020

Если вам нужна только одна строка для каждого идентификатора, вы можете использовать агрегацию:

select id, max(city) as city, max(province) as province,
       max(date) filter (where status = 'success') as date
from t
group by id
having count(*) filter (where status = 'success') > 0;

Обратите внимание, что если у вас может быть несколько успешных дат для каждого идентификатора, вы можете поместить их в ту же строку, используя array_agg() :

       array_agg(date) filter (where status = 'success') as dates
1 голос
/ 09 июля 2020

Возможно, вам поможет оконная функция:

SELECT id, city, province, status, date
FROM (SELECT id,
             max(city) OVER w AS city,
             max(province) OVER w AS province,
             status,
             date
      FROM atable
      WINDOW w AS (PARTITION BY id)) AS q
WHERE status = 'success';
1 голос
/ 09 июля 2020

Здесь вы можете использовать аналитические функции.

SELECT * FROM 
(SELECT T.ID, T.CITY, T.PROVINCE,
        MAX(CASE WHEN STATUS = 'success' THEN DATE END) 
             OVER (PARTITION BY ID ORDER BY DATE) AS DATE,
        ROW_NUMBER() OVER (PARTITION BY ID ORDER BY DATE) AS RN,
        SUM(CASE WHEN STATUS = 'success' THEN 1 ELSE 0 END) 
             OVER (PARTITION BY ID) AS CNT
  FROM YOUR_TABLE T)
 WHERE RN = 1 AND CNT > 0

Поскольку вы изменили данные образца, вы можете использовать GROUP BY следующим образом:

SELECT ID, MAX(CITY) AS CITY, MAX(PROVINCE) AS PROVINCE, 
       MAX(CASE WHEN STATUS = 'success' THEN DATE END) AS DATE
  FROM YOUR_TABLE 
GROUP BY ID
HAVING SUM(CASE WHEN STATUS = 'success' THEN 1 END) > 0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...