2017-10-10 1 views
0

Ich habe zwei Tabellen und die Werte wie dieseVergleichen Sie die beiden Tabellen und aktualisiert den Wert in einer Spalte Flag

`create table InputLocationTable(SKUID int,InputLocations varchar(100),Flag varchar(100)) 
create table Location(SKUID int,Locations varchar(100)) 

insert into InputLocationTable(SKUID,InputLocations) values(11,'Loc1, Loc2, Loc3, Loc4, Loc5, Loc6') 
insert into InputLocationTable(SKUID,InputLocations) values(12,'Loc1, Loc2') 
insert into InputLocationTable(SKUID,InputLocations) values(13,'Loc4,Loc5') 

insert into Location(SKUID,Locations) values(11,'Loc3') 
insert into Location(SKUID,Locations) values(11,'Loc4') 
insert into Location(SKUID,Locations) values(11,'Loc5') 
insert into Location(SKUID,Locations) values(11,'Loc7') 
insert into Location(SKUID,Locations) values(12,'Loc10') 
insert into Location(SKUID,Locations) values(12,'Loc1') 
insert into Location(SKUID,Locations) values(12,'Loc5') 
insert into Location(SKUID,Locations) values(13,'Loc4') 
insert into Location(SKUID,Locations) values(13,'Loc2') 
insert into Location(SKUID,Locations) values(13,'Loc2')` 

Ich brauche die Ausgabe zu erhalten, indem SKUID die von jeder Tabelle und Aktualisieren Sie den Wert in Spalte Flag passend wie im Screenshot zu sehen, ich habe so etwas wie dieser Code versucht

`SELECT STUFF((select ','+ Data.C1 
FROM 
(select 
    n.r.value('.', 'varchar(50)') AS C1 
from InputLocation as T 
    cross apply (select cast('<r>'+replace(replace(Location,'&','&'), ',', '</r><r>')+'</r>' as xml)) as S(XMLCol) 
    cross apply S.XMLCol.nodes('r') as n(r)) DATA 
WHERE data.C1 NOT IN (SELECT Location 
       FROM Location) for xml path('')),1,1,'') As Output` 

aber nicht davon überzeugt, mit Ausgang und ich versuche auch xml Pfad Code zu vermeiden, da die Leistung für diesen Code nicht den ersten Platz ist, muss ich den Ausgang wie der folgende Screenshot. Jede Hilfe würde sehr geschätzt werden.

enter image description here

+0

Sie damit sagen, dass Update Die Flagge Spalte, in INputLocation nicht IN Location Tabelle Standort scolumn –

+0

Ich bin nicht sicher, ob ich Ihre Frage richtig verstanden habe ... Sie sagten, dass Sie mit XML eine Lösung finden verwaltet Weg aber würde lieber vermeiden, das zu verwenden. Nun, "FOR XML PATH" ist afaik die beste und empfohlene Lösung für String-Verkettungen bis SQL Server 2016. 2016 hat MSFT die Funktion STRING_AGG hinzugefügt. In SQL Server 2008 können Sie eine benutzerdefinierte Assembly als Alternative verwenden. Aber das hat seine Schattenseiten. Sehen Sie sich https://www.sqlshack.com/string-concatenation-done-right-part-2-an-effective-technique/ an. –

+0

Hallo, danke für die Wiederholung, ich vermied einfach mit xml Pfad, das heißt nicht, dass ich nicht verwenden sollte und alle, ich benutze SQL Server 2014, also bitte schlagen Sie mir besser Code oder Antwort für diese – Karthik

Antwort

0

Ich glaube, Sie müssen zuerst sehen, warum Sie denken, die XML Ansatz nicht gut genug für Ihre Bedürfnisse ausführt, wie it has actually been shown to perform very well for larger input strings.

Wenn Sie nur von Eingabezeichenfolgen behandeln müssen bis entweder 4000 oder 8000 Zeichen (nicht maxnvarchar und varchar Typen respectively), können Sie eine Tally-Tabelle innerhalb einer Inline-Tabellenwertfunktion which will also perform very well enthalten nutzen. Die Version, die ich verwende, kann am Ende dieses Beitrags gefunden werden.

diese Funktion nutzen wir die Werte in Ihrer InputLocations Spalte aufzuschlüsseln können, obwohl wir noch for xml verwenden müssen, um sie für das gewünschte Format wieder zusammen zu verketten:

-- Define data 
declare @InputLocationTable table (SKUID int,InputLocations varchar(100),Flag varchar(100)); 
declare @Location table (SKUID int,Locations varchar(100)); 

insert into @InputLocationTable(SKUID,InputLocations) values (11,'Loc1, Loc2, Loc3, Loc4, Loc5, Loc6'),(12,'Loc1, Loc2'),(13,'Loc4,Loc5'),(14,'Loc1'); 
insert into @Location(SKUID,Locations) values (11,'Loc3'),(11,'Loc4'),(11,'Loc5'),(11,'Loc7'),(12,'Loc10'),(12,'Loc1'),(12,'Loc5'),(13,'Loc4'),(13,'Loc2'),(13,'Loc2'),(14,'Loc1'); 

--Query 

-- Derived table splits out the values held within the InputLocations column 
with i as 
(
    select i.SKUID 
      ,i.InputLocations 
      ,s.item as Loc 
    from @InputLocationTable as i 
     cross apply dbo.fn_StringSplit4k(replace(i.InputLocations,' ',''),',',null) as s 
) 
select il.SKUID 
     ,il.InputLocations 
     ,isnull('Add ' -- The split Locations are then matched to those already in @Location and those not present are concatenated together. 
       + stuff((select ', ' + i.Loc 
         from i 
          left join @Location as l 
           on i.SKUID = l.SKUID 
            and i.Loc = l.Locations 
         where il.SKUID = i.SKUID 
          and l.SKUID is null 
         for xml path('') 
        ) 
        ,1,2,'' 
        ) 
       ,'No Flag') as Flag 
from @InputLocationTable as il 
order by il.SKUID; 

Ausgang:

+-------+------------------------------------+----------------------+ 
| SKUID |   InputLocations   |   Flag   | 
+-------+------------------------------------+----------------------+ 
| 11 | Loc1, Loc2, Loc3, Loc4, Loc5, Loc6 | Add Loc1, Loc2, Loc6 | 
| 12 | Loc1, Loc2       | Add Loc2    | 
| 13 | Loc4,Loc5       | Add Loc5    | 
| 14 | Loc1        | No Flag    | 
+-------+------------------------------------+----------------------+ 

Für nvarchar Eingang (Ich habe verschiedene Funktionen für varchar und max Typ Eingabe) Dies ist meine Version der String Splitting-Funktion oben verknüpft:

create function [dbo].[fn_StringSplit4k] 
(
    @str nvarchar(4000) = ' '  -- String to split. 
,@delimiter as nvarchar(1) = ',' -- Delimiting value to split on. 
,@num as int = null    -- Which value in the list to return. NULL returns all. 
) 
returns table 
as 
return 
    -- Start tally table with 10 rows. 
with n(n) as (select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1) 

    -- Select the same number of rows as characters in @str as incremental row numbers. 
    -- Cross joins increase exponentially to a max possible 10,000 rows to cover largest @str length. 
    ,t(t) as (select top (select len(isnull(@str,'')) a) row_number() over (order by (select null)) from n n1,n n2,n n3,n n4) 

    -- Return the position of every value that follows the specified delimiter. 
    ,s(s) as (select 1 union all select t+1 from t where substring(isnull(@str,''),t,1) = @delimiter) 

    -- Return the start and length of every value, to use in the SUBSTRING function. 
    -- ISNULL/NULLIF combo handles the last value where there is no delimiter at the end of the string. 
    ,l(s,l) as (select s,isnull(nullif(charindex(@delimiter,isnull(@str,''),s),0)-s,4000) from s) 

select rn 
     ,item 
from(select row_number() over(order by s) as rn 
      ,substring(@str,s,l) as item 
     from l 
    ) a 
where rn = @num 
    or @num is null; 
go 
Verwandte Themen