применить сортировку в вещах, вещи отличные и упорядочить по - PullRequest
1 голос
/ 17 июня 2019

Мне нужно объединить строки с одинаковым значением в одну, используя оператор STUFF.Я заархивировал объединение строк, но последовательность значений неверна.

http://www.sqlfiddle.com/#!18/2f420/1/0

, как вы видите в окне результатов, TypeB находится рядом с TypeA, но последовательность значений Amount не соответствует значениям Type, где 0,09K должно быть рядом с 3k * 1006.*

enter image description here

Как сделать STUFF из различных значений и сохранить последовательность (порядок по rn)?

create table SomeTable (Code int, Type nvarchar(50), Amount nvarchar(50), Date datetime);

insert into SomeTable VALUES(20, 'TypeA', '12k', cast('01/01/2019' as datetime));
insert into SomeTable VALUES(20, 'TypeA', '11k', cast('01/01/2018' as datetime));
insert into SomeTable VALUES(22, 'TypeA', '17k', cast('01/02/2017' as datetime));
insert into SomeTable VALUES(22, 'TypeA', '17k', cast('01/01/2017' as datetime));
insert into SomeTable VALUES(25, 'TypeB', '0.09k', cast('01/02/2019' as datetime));
insert into SomeTable VALUES(25, 'TypeA', '3k', cast('01/01/2019' as datetime));

with t as (

  select 
      row_number() over(partition by st.Code order by st.Date) as rn,
      st.Code, 
      st.Type, 
      st.Amount, 
      st.Date 
  from SomeTable st
)

select 
  t1.Code,
  stuff((select distinct ',' + t.Type from t 
         where t.Code = t1.Code
         for XML path('')), 1,1, '') as Type,
  stuff((select distinct ',' + t.Amount from t 
         where t.Code = t1.Code
         for XML path('')), 1,1, '') as Amount,
  t1.Date
from t as t1
where t1.rn = 1
order by t1.Date

Ответы [ 3 ]

1 голос
/ 17 июня 2019

Как насчет таких попыток?

with t as (
  select 
      row_number() over(partition by st.Code order by st.Date) as rn,
      st.Code, 
      st.Type, 
      st.Amount, 
      st.Date 
  from SomeTable st
),
t2 as (
  select distinct top 100 percent
      st.code,
      st.type,
      st.amount
  from SomeTable st
  order by st.code, st.type, st.amount
)

select 
  t1.Code,
  stuff((select distinct ',' + t2.Type from t2 
         where t2.Code = t1.Code
         for XML path('')), 1,1, '') as Type,
  stuff((select ',' + t2.Amount from t2 
         where t2.Code = t1.Code
         for XML path('')), 1,1, '') as Amount,
  t1.Date
from t as t1
where t1.rn = 1
order by t1.Date
1 голос
/ 17 июня 2019

Применение сортировки к любому результату в SQL выполняется с помощью предложения order by.
Это не функция stuff, которая доставляет вам трудности, а тот факт, что вы не указали order by для подзапросов.
Без условия и order by подзапросы возвращают записи в произвольном порядке - и именно поэтому вы получаете результат, который получаете сейчас.
Однако обратите внимание, что, поскольку порядок результатов произвольный, при следующем запросе вы можете получить другой результат.

Для этого вы должны указать в подзапросах предложение order by, которое генерирует столбцы C.S.V.

Теперь я не совсем уверен, какой порядок вы ожидаете, но, вероятно, это либо сортировка по rn, либо по rn desc (основываясь на изображении, которое я считаю первым).
Однако здесь есть хитрость - поскольку вам нужны разные значения type и amount, вы не можете просто использовать rn в предложении order by - SQL Server вызовет следующую ошибку:

Элементы ORDER BY должны отображаться в списке выбора, если указано SELECT DISTINCT.

Итак, хитрость заключается в том, чтобы не использовать distinct, а вместо этого использовать group by и не использовать rn в предложении order by, а max(rn). Таким образом, вы получите TypeA,TypeB и 3k,0.09k - и это будет согласованно.

Сказав все это - вот пересмотренная версия вашего кода (cte остается неизменным):

select  t1.Code,
  stuff((
            select ','+ t.Type
            from t 
            where t.Code = t1.Code
            group by t.Type
            order by max(rn) 
            for XML path('')
        ), 1,1, '') as Type,
  stuff((select ',' + t.Amount 
         from t 
         where t.Code = t1.Code
         group by  t.Amount 
         order by max(rn) 
         for XML path('')), 1,1, '') as Amount,
  t1.Date
from t as t1
where t1.rn = 1
order by t1.Date

И результаты:

Code    Type            Amount      Date
22      TypeA           17k         2017-01-01
20      TypeA           11k,12k     2018-01-01
25      TypeA,TypeB     3k,0.09k    2019-01-01

NOTE Комментарий Салмана к вопросу (который я видел только сейчас) имеет очень правильное замечание - distinct может быть не совсем подходящим вариантом здесь.
В сценарии, где у вас было TypeA, TypeB, TypeA с соответствующими суммами 10K, 11K, 12K -
Если вы отличаетесь, результат будет TypeA, TypeB и составляет 10K, 11K, 12K - и будет невозможно определить, какая сумма принадлежит какому типу.

1 голос
/ 17 июня 2019

Разместите заказ в сегменте материала:

 select 
  t1.Code,
  stuff((select distinct top 100 percent  ',' + t.Type from t 
         where t.Code = t1.Code order by ',' + t.Type 
         for XML path('')), 1,1, '') as Type,
  stuff((select distinct ',' + t.Amount from t 
         where t.Code = t1.Code
         for XML path('')), 1,1, '') as Amount,
  t1.Date
from t as t1
where t1.rn = 1
order by t1.Date
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...