Porównanie wierszy i rejestracja zmiennych wartości - historia zmian

0

Witam,

Panowie (i Panie) - na prowadźcie jak podejść do tematu bo zaćmienie i osłabienie umysłu mam prze wielkie aktualnie.
Mam tablice z historia zmian na kodzie towarowym coś jak w tych danych testowych (przy czym kolumn jest w sumie 25):

http://www.sqlfiddle.com/#!18/22eee/3/0

Jak widzicie nie jest to najszczęśliwszy sposób na rejestracje zmian ... no ale na tak to zostało wdrożone jakiś czas temu i na tym muszę działać.
Tak czy inaczej do innego raportu/tablicy - muszę dołączyć historie zmian po kodzie od wyznaczonej daty w formie "NazwaKolumny1 staraWartosc, nowaWartosc; NazwaKolumny2 staraWartosc, nowaWartosc;

Czyli bazując na danych z przykładu, otrzymałbym bym (podkreśliłem kolumny tutaj dla lepszej orientacji):

Kod | ZmianyKodu
11111 | D2 dat, ala; D5 123, 666
22222 | D1 kot pies zajac; D2 lok, rrr; D4 aaa, ccc; D5 888, 654;
55555 | D4 aaa, ccc, ddd, eee; D5 888, 654;

Nie wiem jak się za to zabrać .. poradzicie coś ?

Pozdrawiam jak zwykle z góry dzięki za sugestie / pomoc..

2

Na jednorazowe wygenerowanie wyniku pewnie coś takiego wystarczy.
http://www.sqlfiddle.com/#!18/22eee/69

Co do rozwiązania produkcyjnego, pewnie da się to dużo lepiej napisać, więc z chęcią poznam rozwiązania innych.
Pewnie zamiast unii można jakiegoś unpivota zastosować.

2

Sprawa nie jest wbrew pozorom trywialna, bo w pierwszej chwili można pomyśleć, że wystarczy pobrać funkcją grupującą stringi w ten sposób: conctat_string(distinct D1) i pokazać tylko wtedy gdy count(distinct D1) > 0 ale to generuje problem:

  1. kolejność pokazywanych danych
  2. zadziała błędnie jeżeli zmiana będzie taka ala->dat->ala (tak spreparowałem dane dla kolumny d2 dla kodu:11111)

Rozwiązaniem problemu 2 jest takie zapytanie do grupowania stringów (jakby ktoś się zastanawiał co chciałem osiągnąć ;)):

,'D3: ' + STUFF((SELECT
				',' +  RTRIM(CONVERT(VARCHAR(30),D3))
			 FROM (
				select 
				    Kod,
				    dataDO,
				    case when LAG(D3,1) OVER (PARTITION BY KOD ORDER BY dataDo) is null  OR LAG(D3,1) OVER (PARTITION BY KOD ORDER BY dataDo) <> D3 then
					   D3
				    else 
					   '' 
				    end D3
				    from 
				    HistoriaZmian) X
			 WHERE
				LEN(D3)>0
				AND Kod  = dt.Kod
			 ORDER BY
				DATADO
			 FOR XML PATH(''))

Teraz można to ubrać w całość:

with d as (
SELECT 
    KOD
    ,COUNT(DISTINCT D1) cD1
    ,'D1: ' +  STUFF((SELECT
				   ',' + RTRIM(CONVERT(VARCHAR(30),D1))
				FROM (
				    select 
					   Kod,
					   dataDO,
					   case when LAG(D1,1) OVER (PARTITION BY KOD ORDER BY dataDo) is null  OR LAG(D1,1) OVER (PARTITION BY KOD ORDER BY dataDo) <> D1 then
						  D1
					   else 
						  '' 
					   end D1
					from 
					   HistoriaZmian) X
				WHERE
				    LEN(D1)>0
				    AND Kod  = dt.Kod
				ORDER BY
				    DATADO
				FOR XML PATH('')),1,1,'') + ';' tD1
    ,COUNT(DISTINCT D2) cD2
    ,'D2: ' + STUFF((SELECT
				   ',' +  RTRIM(CONVERT(VARCHAR(30),D2))
				FROM (
				    select 
					   Kod,
					   dataDO,
					   case when LAG(D2,1) OVER (PARTITION BY KOD ORDER BY dataDo) is null  OR LAG(D2,1) OVER (PARTITION BY KOD ORDER BY dataDo) <> D2 then
						  D2
					   else 
						  '' 
					   end D2
					from 
					   HistoriaZmian) X
				WHERE
				    LEN(D2)>0
				    AND Kod  = dt.Kod
				ORDER BY
				    DATADO
				FOR XML PATH('')),1,1,'') + ';' tD2
    ,COUNT(DISTINCT D3) cD3
    ,'D3: ' + STUFF((SELECT
				   ',' +  RTRIM(CONVERT(VARCHAR(30),D3))
				FROM (
				    select 
					   Kod,
					   dataDO,
					   case when LAG(D3,1) OVER (PARTITION BY KOD ORDER BY dataDo) is null  OR LAG(D3,1) OVER (PARTITION BY KOD ORDER BY dataDo) <> D3 then
						  D3
					   else 
						  '' 
					   end D3
					from 
					   HistoriaZmian) X
				WHERE
				    LEN(D3)>0
				    AND Kod  = dt.Kod
				ORDER BY
				    DATADO
				FOR XML PATH('')),1,1,'') + ';' tD3
    ,COUNT(DISTINCT D4) cD4
    ,'D4: ' + STUFF((SELECT
				   ',' +  RTRIM(CONVERT(VARCHAR(30),D4))
				FROM (
				    select 
					   Kod,
					   dataDO,
					   case when LAG(D4,1) OVER (PARTITION BY KOD ORDER BY dataDo) is null  OR LAG(D4,1) OVER (PARTITION BY KOD ORDER BY dataDo) <> D4 then
						  D4
					   else 
						  '' 
					   end D4
					from 
					   HistoriaZmian) X
				WHERE
				    LEN(D4)>0
				    AND Kod  = dt.Kod
				ORDER BY
				    DATADO
				FOR XML PATH('')),1,1,'') + ';' tD4
    ,COUNT(DISTINCT D5) cD5
    ,'D5: ' + STUFF((SELECT
				   ',' +  RTRIM(CONVERT(VARCHAR(30),D5))
				FROM (
				    select 
					   Kod,
					   dataDO,
					   case when LAG(D5,1) OVER (PARTITION BY KOD ORDER BY dataDo) is null  OR LAG(D5,1) OVER (PARTITION BY KOD ORDER BY dataDo) <> D5 then
						  D5
					   else 
						  '' 
					   end D5
					from 
					   HistoriaZmian) X
				WHERE
				    LEN(D5)>0
				    AND Kod  = dt.Kod
				ORDER BY
				    DATADO
				FOR XML PATH('')),1,1,'') + ';' tD5
FROM 
  HistoriaZmian dt
group by
 kod
)

select 
    kod
    ,case when cD1 > 1 then tD1 else '' end
    +case when cD2 > 1 then tD2 else '' end
    +case when cD3 > 1 then tD3 else '' end
    +case when cD4 > 1 then tD4 else '' end
    +case when cD5 > 1 then tD5 else '' end
from
d

Straszna rzeźba i obawiam się że może mozno niewydajnie pracować...

http://www.sqlfiddle.com/#!18/0433b/12

0

Hej Hej,

A coś takiego?
http://www.sqlfiddle.com/#!18/22eee/127

0

Napisałem zapytanie z użyciem unpivota, niestety nie mam możliwości sprawdzenia na wersji z 2014 :(
Pewnie string_agg będzie do zamiany na coś innego.
http://www.sqlfiddle.com/#!18/22eee/137

with hz as (
  select Kod, DataOd, DataDo
  ,cast(D1 as char(30)) as D1
  ,cast(D2 as char(30)) as D2
  ,cast(D3 as char(30)) as D3
  ,cast(D4 as char(30)) as D4
  ,cast(D5 as char(30)) as D5
  from HistoriaZmian
)
,r as (
  select Kod, Col, Val, row_number() over (order by Kod, Col, DataDo asc) as rn
  from hz
  unpivot (
    Val for Col in (D1, D2, D3, D4, D5)
  ) t
)
select f.Kod, string_agg(f.Col + ': ' + f.changes, '') within group (order by f.Col) as ZmianyKodu
from (
  select cur.Kod, cur.col, string_agg(cur.Val, ', ') within group (order by cur.rn) as changes
  from r cur
  left join r pre 
  on cur.Kod = pre.Kod and cur.Col = pre.Col and cur.rn = pre.rn + 1
  where (cur.Val <> pre.Val) or (cur.Val is not null and pre.Val is null)
  group by cur.Kod, cur.col
  having count(*) > 1
) f
group by f.Kod
order by f.Kod
;

0

@Seti87: przy Twoim ostatnim kodzie błąd:

The function 'string_agg' may not have a WITHIN GROUP clause.

Funkcja string_agg od wersji 2017 :|

0

Ok - wypadało by podsumować zgodnie z obietnicą.

jak już w sumie wspominałem rozwiązanie @Panczo jest prawidłowe i teoretycznie mogło by zamknąć temat. Niestety "teoretycznie" bo jak sam mówiłeś Panczo nie jest to optymalne i w praktyce na większym secie danych się wywala (z ciekawości zostawiłem na weekend zapytanie ale dziś odkryłem, że się zwyczajnie wywaliło po drodze :| ).
Także proponuje tak temat zostawiam otwarty do piątku - na może jeszcze jakieś sugestie w temacie może coś się uda zoptymalizować :) a jak nie zaakceptuje odpowiedź @Panczo

@Seti87 - Twoje rozwiązanie też wygląda bardzo fajnie - niestety w 2014 nie mogę użyć w/w funkcji, a ostatecznie po wielu próbach nie udało mi się jej zastąpić żeby otrzymać poprawny wynik tak więc poddałem się (może ktoś podpowie jak to podmienić ? ) . Może wtedy Twoje rozwiązanie będzie "szybsze".

Tak czy inaczej wielkie dzięki za podpowiedzi i rozwiązania.

1

Trochę się zmieniły tabele, z pytania źródłowego, ale nie mam za bardzo czasu na przygotowywanie tego w fiddle, więc zrzut jak wyglądają teraz:
screenshot-20180924155741.png

Dodatkowa tabela, dla zestawu danych:
screenshot-20180924155837.png

Pierwsza ma 1 598 042 rekordów druga: 105 349, więc nadal rzeźbimy w g... tylko bardzo dużym ;)

Więc przygotowujemy dane, aby doprowadzić je do takiej postaci:
screenshot-20180924160219.png

Które zapisujemy do tabeli tymczasowej #tmp, a reszta to dynamiczne wygenerowanie zapytania do wyciągnięcia interesujących wartości:

Skrypt zwracający wynik:

with preData as (
Select 
    ach.itemid,
    ValidFrom,
    ISNULL(ach.ValidTo, '2099-12-31') ValidTo,
    rtrim(cast(BusinessCase as varchar(30))) BusinessCase,
    rtrim(cast(SelectionCode as varchar(30))) SelectionCode,
    rtrim(cast(SignalCode as varchar(30))) SignalCode,
    rtrim(cast(Width as varchar(30))) Width,
    rtrim(cast(Unspsc as varchar(30))) Unspsc
 FROM 
    [ArticleChangeHistory] ach
    INNER JOIN finalSetToBeCheck plm   ON ach.ItemID = plm.ITemID AND ISNULL(ach.ValidTo, '2099-12-31') > plm.DateContractPrice
), unp as (
select 
    * 
from 
    preData
    unpivot (
	   Val FOR Col IN (BusinessCase, SelectionCode, SignalCode, Width,  Unspsc)
    ) t
), z as (
select 
    *
    ,  CASE WHEN LAG(val,1) OVER (PARTITION BY itemID,col ORDER BY validTo) IS NULL  OR LAG(val,1) OVER (PARTITION BY itemID,col ORDER BY validTo) <> val THEN
            1
        ELSE 
            0
       END c
from unp)


select ROW_NUMBER() over(partition by itemID,col order by validTo) rn, * into #tmp from z where c=1


declare @i as integer
declare @cols nvarchar(max)
declare @change_col  nvarchar(max)
declare @sql nvarchar(max)
select  @i = max(rn) from #tmp
SET @cols = STUFF((select 
    ' max(case when col = ''' + col + ''' and rn='+n+' then val else null end) as ['+col+n+'], ' 
from (select distinct 
	   col 
	  from 
	 #tmp) t 
	 inner join (select cast(number as varchar(6)) n,number from master..spt_values where type = 'p' and number between 1 and @i
) as l on 1=1 order by Col, number
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')
set  @change_col  = STUFF((select ' ' +
    case when number = 1 then 
	   'case when '+col+'1 <> isnull('+col+'2,'+col+'1) then '''+col+': '' + ' + col+n 
    else 
	   '' 
	end 
	+case when number > 1 then 
	   '+isnull('', ''+' + col+n+','''')' else '' end
   + case when number = @i then '+''; '' else '''' end + ' else '' end 
from (select distinct 
	   col 
	  from 
	 #tmp) t 
	 inner join (select cast(number as varchar(6)) n,number from master..spt_values where type = 'p' and number between 1 and @i
) as l on 1=1 order by Col, number
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @change_col = LEFT(@change_col,len(@change_col)-2) + ' as Changes'
 

set @sql  =  N'select 
			 itemid,
			 '+@change_col+'
		  from (select
				'+@cols+ N'
				itemid
			  from
				#tmp
			 group by 
				itemid
			 ) as dt'



execute (@sql)

drop table #tmp

Zapytanie generowane przez skrypt:

SELECT itemid,
       CASE
           WHEN businesscase1 <> Isnull(businesscase2, businesscase1)
           THEN 'BusinessCase: '+businesscase1+Isnull(', '+businesscase2, '')+Isnull(', '+businesscase3, '')+Isnull(', '+businesscase4, '')+Isnull(', '+businesscase5, '')+Isnull(', '+businesscase6, '')+Isnull(', '+businesscase7, '')+Isnull(', '+businesscase8, '')+'; '
           ELSE ''
       END
	  +CASE
            WHEN selectioncode1 <> Isnull(selectioncode2, selectioncode1)
            THEN 'SelectionCode: '+selectioncode1+Isnull(', '+selectioncode2, '')+Isnull(', '+selectioncode3, '')+Isnull(', '+selectioncode4, '')+Isnull(', '+selectioncode5, '')+Isnull(', '+selectioncode6, '')+Isnull(', '+selectioncode7, '')+Isnull(', '+selectioncode8, '')+'; '
            ELSE ''
        END
	   +CASE
            WHEN signalcode1 <> Isnull(signalcode2, signalcode1)
            THEN 'SignalCode: '+signalcode1+Isnull(', '+signalcode2, '')+Isnull(', '+signalcode3, '')+Isnull(', '+signalcode4, '')+Isnull(', '+signalcode5, '')+Isnull(', '+signalcode6, '')+Isnull(', '+signalcode7, '')+Isnull(', '+signalcode8, '')+'; '
            ELSE ''
        END
	   +CASE
            WHEN unspsc1 <> Isnull(unspsc2, unspsc1)
            THEN 'Unspsc: '+unspsc1+Isnull(', '+unspsc2, '')+Isnull(', '+unspsc3, '')+Isnull(', '+unspsc4, '')+Isnull(', '+unspsc5, '')+Isnull(', '+unspsc6, '')+Isnull(', '+unspsc7, '')+Isnull(', '+unspsc8, '')+'; '
            ELSE ''
        END
	   +CASE
			 WHEN width1 <> Isnull(width2, width1)
			 THEN 'Width: '+width1+Isnull(', '+width2, '')+Isnull(', '+width3, '')+Isnull(', '+width4, '')+Isnull(', '+width5, '')+Isnull(', '+width6, '')+Isnull(', '+width7, '')+Isnull(', '+width8, '')+'; '
			 ELSE ''
		  END AS Changes
FROM
(
    SELECT MAX(CASE
                   WHEN col = 'BusinessCase'
                        AND rn = 1
                   THEN val
                   ELSE NULL
               END) AS [BusinessCase1],
           MAX(CASE
                   WHEN col = 'BusinessCase'
                        AND rn = 2
                   THEN val
                   ELSE NULL
               END) AS [BusinessCase2],
           MAX(CASE
                   WHEN col = 'BusinessCase'
                        AND rn = 3
                   THEN val
                   ELSE NULL
               END) AS [BusinessCase3],
           MAX(CASE
                   WHEN col = 'BusinessCase'
                        AND rn = 4
                   THEN val
                   ELSE NULL
               END) AS [BusinessCase4],
           MAX(CASE
                   WHEN col = 'BusinessCase'
                        AND rn = 5
                   THEN val
                   ELSE NULL
               END) AS [BusinessCase5],
           MAX(CASE
                   WHEN col = 'BusinessCase'
                        AND rn = 6
                   THEN val
                   ELSE NULL
               END) AS [BusinessCase6],
           MAX(CASE
                   WHEN col = 'BusinessCase'
                        AND rn = 7
                   THEN val
                   ELSE NULL
               END) AS [BusinessCase7],
           MAX(CASE
                   WHEN col = 'BusinessCase'
                        AND rn = 8
                   THEN val
                   ELSE NULL
               END) AS [BusinessCase8],
           MAX(CASE
                   WHEN col = 'SelectionCode'
                        AND rn = 1
                   THEN val
                   ELSE NULL
               END) AS [SelectionCode1],
           MAX(CASE
                   WHEN col = 'SelectionCode'
                        AND rn = 2
                   THEN val
                   ELSE NULL
               END) AS [SelectionCode2],
           MAX(CASE
                   WHEN col = 'SelectionCode'
                        AND rn = 3
                   THEN val
                   ELSE NULL
               END) AS [SelectionCode3],
           MAX(CASE
                   WHEN col = 'SelectionCode'
                        AND rn = 4
                   THEN val
                   ELSE NULL
               END) AS [SelectionCode4],
           MAX(CASE
                   WHEN col = 'SelectionCode'
                        AND rn = 5
                   THEN val
                   ELSE NULL
               END) AS [SelectionCode5],
           MAX(CASE
                   WHEN col = 'SelectionCode'
                        AND rn = 6
                   THEN val
                   ELSE NULL
               END) AS [SelectionCode6],
           MAX(CASE
                   WHEN col = 'SelectionCode'
                        AND rn = 7
                   THEN val
                   ELSE NULL
               END) AS [SelectionCode7],
           MAX(CASE
                   WHEN col = 'SelectionCode'
                        AND rn = 8
                   THEN val
                   ELSE NULL
               END) AS [SelectionCode8],
           MAX(CASE
                   WHEN col = 'SignalCode'
                        AND rn = 1
                   THEN val
                   ELSE NULL
               END) AS [SignalCode1],
           MAX(CASE
                   WHEN col = 'SignalCode'
                        AND rn = 2
                   THEN val
                   ELSE NULL
               END) AS [SignalCode2],
           MAX(CASE
                   WHEN col = 'SignalCode'
                        AND rn = 3
                   THEN val
                   ELSE NULL
               END) AS [SignalCode3],
           MAX(CASE
                   WHEN col = 'SignalCode'
                        AND rn = 4
                   THEN val
                   ELSE NULL
               END) AS [SignalCode4],
           MAX(CASE
                   WHEN col = 'SignalCode'
                        AND rn = 5
                   THEN val
                   ELSE NULL
               END) AS [SignalCode5],
           MAX(CASE
                   WHEN col = 'SignalCode'
                        AND rn = 6
                   THEN val
                   ELSE NULL
               END) AS [SignalCode6],
           MAX(CASE
                   WHEN col = 'SignalCode'
                        AND rn = 7
                   THEN val
                   ELSE NULL
               END) AS [SignalCode7],
           MAX(CASE
                   WHEN col = 'SignalCode'
                        AND rn = 8
                   THEN val
                   ELSE NULL
               END) AS [SignalCode8],
           MAX(CASE
                   WHEN col = 'Unspsc'
                        AND rn = 1
                   THEN val
                   ELSE NULL
               END) AS [Unspsc1],
           MAX(CASE
                   WHEN col = 'Unspsc'
                        AND rn = 2
                   THEN val
                   ELSE NULL
               END) AS [Unspsc2],
           MAX(CASE
                   WHEN col = 'Unspsc'
                        AND rn = 3
                   THEN val
                   ELSE NULL
               END) AS [Unspsc3],
           MAX(CASE
                   WHEN col = 'Unspsc'
                        AND rn = 4
                   THEN val
                   ELSE NULL
               END) AS [Unspsc4],
           MAX(CASE
                   WHEN col = 'Unspsc'
                        AND rn = 5
                   THEN val
                   ELSE NULL
               END) AS [Unspsc5],
           MAX(CASE
                   WHEN col = 'Unspsc'
                        AND rn = 6
                   THEN val
                   ELSE NULL
               END) AS [Unspsc6],
           MAX(CASE
                   WHEN col = 'Unspsc'
                        AND rn = 7
                   THEN val
                   ELSE NULL
               END) AS [Unspsc7],
           MAX(CASE
                   WHEN col = 'Unspsc'
                        AND rn = 8
                   THEN val
                   ELSE NULL
               END) AS [Unspsc8],
           MAX(CASE
                   WHEN col = 'Width'
                        AND rn = 1
                   THEN val
                   ELSE NULL
               END) AS [Width1],
           MAX(CASE
                   WHEN col = 'Width'
                        AND rn = 2
                   THEN val
                   ELSE NULL
               END) AS [Width2],
           MAX(CASE
                   WHEN col = 'Width'
                        AND rn = 3
                   THEN val
                   ELSE NULL
               END) AS [Width3],
           MAX(CASE
                   WHEN col = 'Width'
                        AND rn = 4
                   THEN val
                   ELSE NULL
               END) AS [Width4],
           MAX(CASE
                   WHEN col = 'Width'
                        AND rn = 5
                   THEN val
                   ELSE NULL
               END) AS [Width5],
           MAX(CASE
                   WHEN col = 'Width'
                        AND rn = 6
                   THEN val
                   ELSE NULL
               END) AS [Width6],
           MAX(CASE
                   WHEN col = 'Width'
                        AND rn = 7
                   THEN val
                   ELSE NULL
               END) AS [Width7],
           MAX(CASE
                   WHEN col = 'Width'
                        AND rn = 8
                   THEN val
                   ELSE NULL
               END) AS [Width8],
           itemid
    FROM #tmp
    GROUP BY itemid
) AS dt;  

Na moim serwerze trwa to 30 sekund...

1

Jest jeszcze jedna możliwość, użycie funkcji agregującej napisanej w CLR, można pobrać tutaj: https://github.com/orlando-colamatteo/ms-sql-server-group-concat-sqlclr

I użyć w zapytaniu:

with preData as (
Select 
    ach.itemid,
    ValidFrom,
    ISNULL(ach.ValidTo, '2099-12-31') ValidTo,
    rtrim(cast(BusinessCase as varchar(30))) BusinessCase,
    rtrim(cast(SelectionCode as varchar(30))) SelectionCode,
    rtrim(cast(SignalCode as varchar(30))) SignalCode,
    rtrim(cast(Width as varchar(30))) Width,
    rtrim(cast(Unspsc as varchar(30))) Unspsc
 FROM 
    [ArticleChangeHistory] ach
    INNER JOIN finalSetToBeCheck plm   ON ach.ItemID = plm.ITemID AND ISNULL(ach.ValidTo, '2099-12-31') > plm.DateContractPrice
), unp as (
select 
    * 
from 
    preData
    unpivot (
	   Val FOR Col IN (BusinessCase, SelectionCode, SignalCode, Width,  Unspsc)
    ) t
), z as (
select 
    *
    ,  CASE WHEN LAG(val,1) OVER (PARTITION BY itemID,col ORDER BY validTo) IS NULL  OR LAG(val,1) OVER (PARTITION BY itemID,col ORDER BY validTo) <> val THEN
            1
        ELSE 
            0
       END c
from unp), x as (
select right('00' + convert(varchar(4),ROW_NUMBER() over(partition by itemID,col order by validTo)),2) + '. ' rn, *  from z where c=1
)
select
    itemid
    ,dbo.GROUP_CONCAT_D(col+': ' + c,'; ') [changes]
from (
    select
	   itemid
	   ,col
	   ,dbo.GROUP_CONCAT_S(rn+val,1) c
    from
	   x
    group by
	   itemid
	   ,col
    having
	   COUNT(val)>1) d
group by
    itemid
0

Panczo ... cóż mogę rzec... nawet z rzeźbienia w g... ;) może wyjść, że tak powiem "piece of art". Twój kod jest genialny - jest tak genialny, że po prawdzie ciągle go jeszcze przetrawiam bo normalnie za wąski w barach jestem żeby go przyjąć tak na klatę za jednym zamachem.
Także mam nadzieję, że wybaczysz mi jak będę z czasem jeszcze w tym wątku zadawał pytania odnośnie powyższego bo bardziej od działającego rozwiązania (a to działa jak ta lala - u mnie całość około 40 sec) - chce się uczyć od mądrzejszych ode mnie. A nie powiem w Twoim kodzie w pewnych momentach się zwyczajnie gubię .

Wielkie dzięki!

0
Panczo napisał(a):

Jest jeszcze jedna możliwość, użycie funkcji agregującej napisanej w CLR, można pobrać tutaj: https://github.com/orlando-colamatteo/ms-sql-server-group-concat-sqlclr

I użyć w zapytaniu:

with preData as (
Select 
    ach.itemid,

... CUT ...

Powiem tak - faktycznie fajnie to wygląda. Nie da się ukryć, że rozwiązanie jest zgrabniejsze z powodu choćby mniejszej ilości linijek no i działa szybciej (choć z tego co wyczytałem z dokumentacji tego CLR nie musi to być regułą). Ma jednak mały szkopuł który mi przeszkadza. To dodanie "numeru zmiany" czyli "01." itd

BusinessCase: 01. DFS,02. DTO; SelectionCode: 01. 700,02. 601,03. 700; SignalCode: 01. UI1,02. 

Z tego co testowałem numer musi być żeby pokazywał poprawnie kolejność zmian w innym wypadku posortuje rosnąco jak:

BusinessCase: DFS,DTO; SignalCode: ,UI1; SelectionCode: 601,700,700

I wychodzi bzdura bo zmiana Selection Code była z 700 na 601 i ponownie później na 700.

1 użytkowników online, w tym zalogowanych: 0, gości: 1