2017-02-07 8 views
2

ich wie folgt eine Tabelle haben:T-SQL in einem Feld Setzen der Durchschnitt der Bindestrich getrennten Werten in einem anderen Feld

ID | FIX_1 | FTO | FIX_2      | 
_____________________________________________________ 
1 |  | 15452 |1.3-1.7-1.8-2.4-2.0   | 
2 |  | 15454 |1.4-1.1-1.4-2.7-2.6-1.8-2.4 | 
3 |  | 15454 |1.9-1.3-1.3     | 
.... ...... .... ................. 
.... ...... .... ................. 
100 |  | 15552 |0.4-1.7-1.2-2.1-2.6-1.6  | 

ich brauche eine select mit FIX_1 Feld gleich dem Durchschnitt der Bindestrich getrennte Werte im Feld FIX_2. Ist es mit T-SQL ohne Verwendung der temporären Tabelle möglich? Vielen Dank im Voraus

+1

Können Sie zeigen Ihre erwartete Ausgabe – TheGameiswar

+0

Warum keine temporäre Tabelle? Wenn Sie keine temporäre Tabelle haben können, gehe ich davon aus, dass Sie keine Funktionen erstellen können? – iamdave

+0

Die FIX_1-Feldausgabe muss lauten: 1,8 für den Datensatz mit ID = 1, 1,9 für den Datensatz mit ID = 2, 1,5 für den Datensatz mit ID = 3 und 1,6 für den Datensatz mit ID = 100 –

Antwort

2

Option mit einem UDF

Declare @YourTable table (ID int,FIX_1 money,FTO int,FIX_2 varchar(max)) 
Insert Into @YourTable values 
(1,null,15452,'1.3-1.7-1.8-2.4-2.0'), 
(2,null,15454,'1.4-1.1-1.4-2.7-2.6-1.8-2.4'), 
(3,null,15454,'1.9-1.3-1.3') 

Update @YourTable Set FIX_1=B.Value 
From @YourTable A 
Cross Apply (
       Select Value = Avg(cast(RetVal as money)) 
       From (Select * from [dbo].[udf-Str-Parse](A.FIX_2,'-')) B1 
      ) B 

Select * From @YourTable 

Option ohne UDF

Update @YourTable Set FIX_1=B.Value 
From @YourTable A 
Cross Apply (
       Select Value = Avg(cast(RetVal as money)) 
       From (
         Select RetSeq = Row_Number() over (Order By (Select null)) 
           ,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)'))) 
         From (Select x = Cast('<x>' + replace((Select replace(A.FIX_2,'-','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A 
         Cross Apply x.nodes('x') AS B(i) 
        ) B1 
      ) B 

Beide zurückkehren würde

ID FIX_1 FTO  FIX_2 
1 1.84 15452 1.3-1.7-1.8-2.4-2.0 
2 1.9142 15454 1.4-1.1-1.4-2.7-2.6-1.8-2.4 
3 1.50 15454 1.9-1.3-1.3 
wenn

Die UDF benötigt

CREATE FUNCTION [dbo].[udf-Str-Parse] (@String varchar(max),@Delimiter varchar(10)) 
Returns Table 
As 
Return ( 
    Select RetSeq = Row_Number() over (Order By (Select null)) 
      ,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)'))) 
    From (Select x = Cast('<x>' + replace((Select replace(@String,@Delimiter,'§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A 
    Cross Apply x.nodes('x') AS B(i) 
); 
--Thanks Shnugo for making this XML safe 
--Select * from [dbo].[udf-Str-Parse]('Dog,Cat,House,Car',',') 
--Select * from [dbo].[udf-Str-Parse]('John Cappelletti was here',' ') 
--Select * from [dbo].[udf-Str-Parse]('this,is,<test>,for,< & >',',') 
+0

beziehen Sie sich auf einen Beitrag oder eine Antwort von @Shnugo, wenn ja, denke ich, dass dies eine korrekte Zuschreibung benötigt ?! wenn kein Problem. – Tanner

+0

@Tanner Eigentlich ist dies eines meiner parse-Dienstprogramme, aber Shnugo schlug eine XML-sichere Analyse in einem anderen Post vor (den ich aufgriff). Dies ist ein Tipp für ihn. –

+0

kein Problem, es sah aus wie ein Versuch der Zuschreibung, aber es war nicht klar – Tanner

0

mit einer benutzerdefinierten Funktion ...

create FUNCTION dbo.AvgOfDashSepVals (@vals varchar(500)) 
returns float as 
BEGIN 
declare @avg decimal 
declare @cnt int = 0 
declare @sum float = 0.0 
While charIndex('-', @vals) > 0 Begin 
     if isnumeric(left(@vals, charIndex('-', @vals)-1)) = 0 
     return null   
    set @cnt+= 1 
    set @sum += cast(left(@vals, charIndex('-', @vals)-1) as float) 
    set @vals = substring(@vals, charIndex('-', @vals)+1, len(@vals)) 
End 
RETURN case @cnt when 0 then null else @sum/@cnt end 

dann Tabelle ändern, um eine berechnete Spalte hinzuzufügen.

alter table myTable 
    add Fix_1 as ([dbo].[AvgOfDashSepVals]([Fix_2])) 
+0

Gute Arbeit! Ich habe eine Funktion wie Ihr udf erstellt, aber wenn ich versuche, dbo.AvgOfDashSepVals ([FIX_2]) zu wählen, bekam ich die Nachricht 'Divide by zero error encountered'. Weißt du, warum? Danke –

+0

wahrscheinlich, weil es auf einer leeren Zeichenfolge läuft ('@ cnt' = 0) Ich habe Code hinzugefügt, um das zu behandeln. –

+0

Wunderbar! Es ist fast perfekt, aber wenn im Feld FIX_2 nur ein Wert ist, gibt die Funktion NULL zurück. Ist es möglich, von der dritten Stelle nach dem Dezimalpunkt auf dem Skalarergebnis zu schneiden? –

0
Declare @YourTable table (ID int,FIX_1 money,FTO int,FIX_2 varchar(max)) 
    Insert Into @YourTable values 
    (1,null,15452,'1.3-1.7-1.8-2.4-2.0'), 
    (2,null,15454,'1.4-1.1-1.4-2.7-2.6-1.8-2.4'), 
    (3,null,15454,'1.9-1.3-1.3'), 
    (4,null,15454,'1.5') 

;WITH cte AS 
(
    SELECT ID, SUBSTRING(FIX_2, 1, CHARINDEX('-',FIX_2) - 1) AS VALUE, SUBSTRING(FIX_2, CHARINDEX('-',FIX_2) + 1, LEN(FIX_2)) AS NEW_FIX_2 
    FROM @YourTable 
    WHERE CHARINDEX('-',FIX_2) > 0 
    UNION ALL 
    SELECT cte.ID, SUBSTRING(NEW_FIX_2, 1, CHARINDEX('-',NEW_FIX_2) - 1) AS VALUE, SUBSTRING(NEW_FIX_2, CHARINDEX('-',NEW_FIX_2) + 1, LEN(NEW_FIX_2)) AS NEW_FIX_2 
    FROM @YourTable y 
     JOIN cte ON cte.ID = y.ID 
    WHERE CHARINDEX('-', NEW_FIX_2) > 0 
    UNION ALL 
    SELECT ID, NEW_FIX_2, NULL 
    FROM cte 
    WHERE CHARINDEX('-', NEW_FIX_2) = 0 
) 
SELECT t.ID, ISNULL(v.VALUE, t.FIX_2) AS FIX_1, t.FTO, t.FIX_2 
FROM @YourTable t 
    LEFT JOIN (
     SELECT cte.ID, AVG(CAST(cte.VALUE AS MONEY)) AS VALUE 
     FROM cte 
     GROUP BY cte.ID 
) v ON v.ID = t.ID 
Verwandte Themen