2010-02-05 8 views
5

Ich habe eine Adressspalte in einer Tabelle, die ich in einer SQL Server 2005-Spalte in mehrere Spalten aufteilen muss. Ich muss die Spalte im Zeilenvorschubzeichen chr (10), und es könnte 1 bis 4 Zeilen (0 bis 3 Zeilenvorschübe) in der Spalte geben. Im Folgenden finden Sie einige Beispiele dafür, was ich tun muss. Was ist der einfachste Weg dies zu erreichen?Spalte "Address" in separate Spalten in der SQL-Ansicht

Examples: 

Address     Address1  Address2  Address3   Address4 
------------  = ----------- ----------- ----------------- --------- 
My Company    My Company  123 Main St. Somewhere,NY 12345 
123 Main St.   
Somewhere,NY 12345 

Address     Address1  Address2  Address3  Address4 
------------  = ------------ ---------- ----------- --------- 
123 Main St.   123 Main St. 
+0

Können die Daten * nicht * in einer einzigen Spalte gespeichert werden? –

+0

Alle Adresszeilen sind in einer einzigen Spalte gespeichert. – Jamie

Antwort

3

dies wird aufgeteilt, um die Adresse, die durch die ParseName Funktion und Kombinieren, dass mit COALESCE den richtigen Informationen in der richtigen Spalte

zu greifen, wenn Sie mehr als 4 Zeilen dieses Verfahren funktioniert, funktioniert nicht

bearbeiten haben: den Code hinzugefügt den Auftrag

create table #test (address varchar(1000)) 

    --test data 
    insert #test values('My Company 
    123 Main St.   
    Somewhere,NY 12345') 

    insert #test values('My Company2 
    666 Main St. 
    Bla Bla  
    Somewhere,NY 12345') 

    insert #test values('My Company2') 

    --split happens here 
          select 
replace(parsename(address,ParseLen +1),'^','') as Address1, 
replace(parsename(address,ParseLen),'^','') as Address2, 
replace(parsename(address,ParseLen -1),'^','') as Address3, 
replace(parsename(address,ParseLen -2),'^','') as Address4 
from(
select case ascii(right(address,1)) when 10 then 
replace(replace(left(address,(len(address)-1)),'.','^'),char(10),'.') 
else 
replace(replace(address,'.','^'),char(10),'.') end as address, 
case ascii(right(address,1)) when 10 then 
len(replace(replace(address,'.','^'),char(10),'.')) - 
len(replace(replace(address,'.','^'),char(10),'')) -1 
else 
len(replace(replace(address,'.','^'),char(10),'.')) - 
len(replace(replace(address,'.','^'),char(10),'')) end as ParseLen 
from #test) x 
+0

Dies macht eine gute Arbeit der Zerlegung der Stücke, aber die Parsename-Funktion füllt ihr Array in umgekehrter Reihenfolge. Also wenn Sie etwas wie 123.456.789 haben, gibt es 1 = 789, 2 = 456 und 3 = 123 zurück. Und wenn Sie 123.456 haben, gibt es 1 = 456 und 2 = 123 zurück. In beiden Szenarien benötige ich 1 = 123, 2 = 456 und im ersten Beispiel 3 = 789. Nicht sicher, ob das klar ist. Ich habe das Gefühl, dass ich das mit deiner Koaleszenz-Methode machen könnte, und zwar in umgekehrter Reihenfolge oder so, aber ich finde es nicht richtig. – Jamie

+0

hat den Code hinzugefügt, um die Reihenfolge umzukehren – SQLMenace

+0

Ok, es ist fast da. Das einzige Problem, das ich jetzt sehe, ist, dass NULL für alle vier Felder zurückgegeben wird, wenn am Ende des Quellfelds ein Zeilenvorschub vorhanden ist. Mit anderen Worten, es gibt eine leere letzte Zeile. Gibt es eine Möglichkeit, irgendwelche Zeilenvorschübe und/oder Leerzeichen am Ende zu entfernen, die es möglicherweise wegwerfen? Danke für Ihre Hilfe! SQLMenace! – Jamie

0

Parsen von Text in SQL macht keinen Spaß. Wenn ich so etwas machen müsste, würde ich die Spalte in eine CSV-Textdatei exportieren und sie in einer Skriptsprache wie Perl/PHP/Python analysieren. Auf diese Weise kann ich die eingebauten String-Funktionen und den regulären Ausdruck der Skriptsprache nutzen.

1

Dies ist furchtbar böse umgekehrt ... ich empfehle, dass, wenn Sie möchten, jede Adressleitung separat behandeln, dass Sie es richtig lagern in den ersten Platz. Anstatt das zu tun, was Sie tun, fügen Sie die zusätzlichen Spalten hinzu, beheben Sie die vorhandenen Daten einmal (anstatt es jedes Mal zu reparieren, wenn Sie eine Abfrage ausführen), und passen Sie dann die gespeicherte Prozedur an, die die Einfügung/Aktualisierung vornimmt damit es die anderen Spalten benutzt.

DECLARE @Address TABLE(id INT IDENTITY(1,1), ad VARCHAR(MAX)); 

INSERT @Address(ad) SELECT 'line 1 
line 2 
line 3 
line 4' 
UNION ALL SELECT 'row 1 
row 2 
row 3' 
UNION ALL SELECT 'address 1 
address 2' 
UNION ALL SELECT 'only 1 entry here' 
UNION ALL SELECT 'let us try 5 lines 
line 2 
line 3 
line 4 
line 5'; 

SELECT 
    id, 
    Line1 = REPLACE(REPLACE(COALESCE(Line1, ''), CHAR(10), ''), CHAR(13), ''), 
    Line2 = REPLACE(REPLACE(COALESCE(Line2, ''), CHAR(10), ''), CHAR(13), ''), 
    Line3 = REPLACE(REPLACE(COALESCE(SUBSTRING(Rest, 1, COALESCE(NULLIF(CHARINDEX(CHAR(10), Rest), 0), LEN(Rest))), ''), CHAR(10), ''), CHAR(13), ''), 
    Line4 = REPLACE(REPLACE(COALESCE(SUBSTRING(Rest, NULLIF(CHARINDEX(CHAR(10), Rest) + 1, 1), LEN(Rest)), ''), CHAR(10), ''), CHAR(13), '') 
FROM 

(
    SELECT 
     id, 
     ad, 
     Line1, 
     Line2 = SUBSTRING(Rest, 1, COALESCE(NULLIF(CHARINDEX(CHAR(10), Rest), 0), LEN(Rest))), 
     Rest = SUBSTRING(Rest, NULLIF(CHARINDEX(CHAR(10), Rest) + 1, 1), LEN(Rest)) 
    FROM 
    (
     SELECT 
      id, 
      ad, 
      Line1 = SUBSTRING(ad, 1, COALESCE(NULLIF(CHARINDEX(CHAR(10), ad), 0), LEN(ad))), 
      Rest = SUBSTRING(ad, NULLIF(CHARINDEX(CHAR(10), ad) + 1, 1), LEN(ad)) 
     FROM 
      @address 
    ) AS x 
) AS y 
ORDER BY id; 

Denis' ParseName() Trick ist viel aufgeräumter natürlich, aber man muss sehr vorsichtig sein, über ein Ersatzzeichen verwenden, das wirklich unmöglich ist natürlich in den Daten angezeigt werden. Das Karat (^) ist wahrscheinlich eine gute Wette, aber wie gesagt, du musst vorsichtig sein.

Es gibt auch Software-Pakete, die wirklich gut sind, Adresse und andere demographische Daten zu schrubben. Aber das Bereinigen der Dateneingabe ist hier das Wichtigste, das ich weiter betonen werde ... wenn jede Adresszeile separat behandelt werden soll, dann speichern Sie sie auf diese Weise.

+0

Ich stimme absolut 100% zu, aber in diesem speziellen Fall habe ich keine Kontrolle über die Struktur der Daten. Es ist frustrierend, aber es ist was es ist. – Jamie

+1

Nun, solange die Benutzer bereit sind, auf die Ansicht zu warten, um diese Aufspaltung jedes Mal durchzuführen, wenn Sie eine Abfrage ausführen ... dann haben Sie wohl recht, es ist was es ist (beschissenes Design). –

Verwandte Themen