Как сделать запрос sql Select таким образом, чтобы некоторые столбцы оставались пустыми в последующих строках, когда закрытие этой строки имеет повторяющееся значение из указанной выше строки? - PullRequest
0 голосов
/ 19 июня 2020

У меня есть такая таблица.

 Name|  Id |  cost
  ----------------
  A  |  1  |  1000
  ----------------
  A  |  1  |  2000
  ----------------
  B  |  2  |  3000
  ----------------
  B  |  2  |  4000

Примечание: данные уже отсортированы

Мне нужен результат:

 Name|  Id |  cost
  ----------------
  A  |  1  |  1000
  ----------------
     |     |  2000
  ----------------
  B  |  2  |  3000
  ----------------
     |     |  4000

Поскольку «A» уже присутствует в нашем запросе, следующая строка должна иметь пустое значение в «Name», а также идентификатор, связанный с «A», равен 1, который также повторяется, следовательно, он также должен быть пустым. Аналогично обстоит дело с B.

Как добиться этого в одном запросе выбора?

Ответы [ 3 ]

0 голосов
/ 19 июня 2020

Можем ли мы сделать

with tb(Name,  Id ,  cost) as (
 select 'A'  ,  1  ,  1000 union all
  select 'A'  ,  1  ,  2000 union all
  select 'B'  ,  2  ,  3000 union all
  select 'B'  ,  2  ,  4000
  )

  select
    case when Row_Nb = 1 then Name else '' end as Name
    ,  case when Row_Nb = 1 then Id else null end as Id 
    ,  cost
  from(
    select row_number() OVER(partition by  Name, id order by cost) AS Row_Nb, tb.*
    from tb
  )x
0 голосов
/ 19 июня 2020

Я не рекомендую делать это как запрос к базе данных. Набор результатов будет содержать строки, которые не имеют смысла, если вы не видите строки над ними - и это не способ SQL.

Я бы предложил сначала агрегировать и поместить затраты в одну строку :

select name, id, string_agg(cost, ', ') as costs
from t
group by name, id;

Если вы действительно настаиваете на этом наборе результатов, очень важно иметь order by во внешнем запросе, потому что без order by результаты может быть в любом порядке. Следовательно, я думаю, что лучшее решение:

select (case when seqnum = 1 then name end) as name,
       (case when seqnum = 1 then id end) as id,
       cost
from (select t.*, row_number() over (partition by name, id order by cost) as seqnum
      from t
     ) t
order by name, id, seqnum
0 голосов
/ 19 июня 2020

Вы можете использовать row_number():

select
    case when row_number() over(partition by name, id order by cost) = 1
        then name
    end name,
    case when row_number() over(partition by name, id order by cost) = 1
        then id
    end id,
    cost
from mytable

Это предполагает, что вам нужны (name, id) кортежи, упорядоченные по cost (как показано в ваших данных примера). Если вы хотите использовать другой столбец упорядочивания, вы можете изменить предложение order by оконных функций.

...