Значение нулевой строки, если данные одинаковы в столбце для выбранного столбца postgresql sql

#sql #postgresql #postgresql-9.6

Вопрос:

У меня есть такой столик:

   cms_code  | product 
------------ ---------
 55381XA384 | MS
 55381XA384 | MS
 55381XA384 | HSD
 55381XA384 | HSD
 55381XA382 | HSD
 55381XA382 | XP
 55381XA382 | MS
 55381XA382 | HSD
 55381XA382 | HSD
 

Теперь мне нужен такой результат, как этот:

   cms_code  | product 
------------ ---------
 55381XA384 | MS
 NULL       | MS
 NULL       | HSD
 NULL       | HSD
 55381XA382 | HSD
 NULL       | XP
 NULL       | MS
 NULL       | HSD
 NULL       | HSD
 

Комментарии:

1. Почему вы отметили свой вопрос с помощью MySQL и Microsoft SQL Server, если вы используете PostgreSQL?

Ответ №1:

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

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

 select (case when row_number() over (partition by cms_code order by <ordering col< = 1
             then cms_code
        end) as cms_code, product_code
from t
order by cms_code, <ordering col>;
 

Без столбца заказа вы также можете сделать:

 with cte as (
      select t.*, row_number() over (partition by cms_code order by cms_code) as seqnum
      from t
     )
select (case when seqnum = 1 then cms_code end) as cms_code,
       product_code
from t
order by cms_code, seqnum;
 

В обоих случаях вам нужно указать order by во внешнем запросе, чтобы гарантировать, что результирующий набор упорядочен таким образом, чтобы «первая» строка содержала cms_code .

Ответ №2:

вы можете использовать оконные функции для нумерации строк и установки последующих значений null , сохраняя значение cms_code только для строки № 1.

 select 
  case 
    when row_number() over (partition by cms_code) = 1 then cms_code 
    else null 
  end cms_code
, product_code
from my_table
order by cms_code
 

Комментарии:

1. @KaranChaudhari . . . Нет, это не «работает идеально». Может показаться, что это работает, но без стабильности order by во внешнем запросе результирующий набор не имеет гарантированного порядка.

2. @GordonLinoff, будет row_number() over (partition by cms_code order by cms_code) производить нумерацию строк , которая более стабильна, чем row_number() over (partition by cms_code) , и почему

3. @HaleemurAli …. Нет , просто некоторые базы данных (и стандарт) требуют order by этого, поэтому я обычно просто включаю это.

Ответ №3:

Я предполагаю, что вы хотите, чтобы значение null для всех значений cms_code было одинаковым после первого значения. Поправьте меня, если я ошибаюсь, Приведенный ниже запрос может быть использован для того же:

 SELECT 
  CASE
    WHEN ROW_NUMBER() OVER(PARTITION BY cms_code order by product) = 1 
    THEN NULL 
    ELSE cms_code 
  END AS cms_code,product 
FROM table;