2016-06-02 28 views
0

Ich habe über 7 Millionen Zeilen, sonst würde ich Excel verwenden.SQL Trennadresse in mehrere Spalten mit Leerzeichen

Meine Adressspalte hat eine unterschiedliche Anzahl von Wörtern. Einige sind so kurz wie 123 Bay Street, während andere so lang sein können wie 1234 West Spring Hill Drive Apt 123.

Mein Ziel ist es, jedes Wort in eine eigene Spalte zu setzen. Ich war in der Lage, das erste Wort zu bekommen, mit der Abfrage unten. Aber ich kann keine effiziente Abfrage erstellen, um den Rest zu erledigen.

update X 
set X.Address_number = Y.[address] 
from 
    (SELECT 
      unique_id, 
      CASE 
      WHEN SUBSTRING(phy_addr1, 1, CHARINDEX(' ', phy_addr1)) = '' 
       THEN phy_addr1 + ' ' 
      ELSE SUBSTRING(phy_addr1, 1, CHARINDEX(' ', phy_addr1)) 
      END 'address' 
     FROM 
     [RD_GeoCode].[dbo].[PA_Stg_excel]) as Y 
    inner join 
     [RD_GeoCode].[dbo].[rg_ApplicationData_AllForms_20160401_address] as X on X.unique_id = Y.unique_id 
    where 
     X.Address_number is null 
+5

Warum möchten Sie * jedes Wort in eine eigene Spalte setzen? Das scheint mir verrückt zu sein. – eggyal

+0

Das klingt nach einer sehr schlechten Idee, aber Sie müssen zuerst Ihre Adresswerte analysieren. Hier sind einige großartige Splitter. http://sqlperformance.com/2012/07/t-sql-queries/split-strings Dann müssen Sie einen dynamischen Drehpunkt machen, um jeden Wert in eine neue Spalte zu setzen. Meine Frage ist jedoch, was ist der Punkt? Was können Sie möglicherweise gewinnen, indem Sie Ihre Daten so trennen? –

+1

Hallo Nick. Was ist das Endziel/Problem, das gelöst werden muss? Vielleicht gibt es einen anderen Ansatz, der mehr Sinn ergibt. – DMason

Antwort

1

Sie benötigen einen Numbers Tisch haben und einer der split strings mentioned here.once Sie haben das, dann seine einfache ..

----- String Splitterfunktion

CREATE FUNCTION dbo.SplitStrings_Numbers 
(
    @List  NVARCHAR(MAX), 
    @Delimiter NVARCHAR(255) 
) 
RETURNS TABLE 
WITH SCHEMABINDING 
AS 
    RETURN 
    (
     SELECT Item = SUBSTRING(@List, Number, 
     CHARINDEX(@Delimiter, @List + @Delimiter, Number) - Number) 
     FROM dbo.Numbers 
     WHERE Number <= CONVERT(INT, LEN(@List)) 
     AND SUBSTRING(@Delimiter + @List, Number, LEN(@Delimiter)) = @Delimiter 
    ); 
GO 

Sie können die obige Funktion wie folgt verwenden.

select 
* 
from yourtable t 
cross apply 
dbo.SplitStrings_Numbers(t.address,' ') b 

anstatt Werte in dieselbe Tabelle zu aktualisieren, sugge ich st eine andere Tabelle erstellen, die Links zu über table.This erfordert einige Schemaänderung, um Ihre bestehenden Tabelle

create table addressreferences 
(
addresss varchar(300), 
delimitedvalue varchar(100) 
) 

insert into addressreferences 
select 
    address,b.* 
    from yourtable t 
    cross apply 
    dbo.SplitStrings_Numbers(t.address,' ') b 

Dies ist nur ein Pseudo-Code, um eine Idee zu geben hat, werden Sie kümmern sich um Referenzen nehmen müssen ... Aktualisieren derselben Tabelle wird nicht funktionieren, weil Sie nicht wissen, wie viele Zeilen eine Adressspalte umfassen kann

Update:
ich denke, ein Trigger wird besser Anzug für Ihr Szenario anstelle von Referenzen ..Aber Sie müssen Führen Sie zuerst eine Insert-Tabelle für vorhandene Werte ein. Hier ist ein Pseudocode.

+0

Irgendwelche Kommentare wären hilfreich, warum dies heruntergeregelt wurde? – TheGameiswar

+0

Vielen Dank für Ihre schnelle Antwort. Nur um zu verdeutlichen, wenn ich sage, dass ich eine Nummerentabelle brauche. meinst du ich muss die adressennummer trennen? – ObiWanCannoli

+0

Noa-Tabelle ist wie normale Tabelle, die Zahlen enthält. Hier sind seine Anwendungsfälle .. http://dba.stackexchange.com/questions/11506/why-are-numbers-tables-invaluable – TheGameiswar

1

Eine Sequenztabelle ist eine gute Sache. Wie in Louis Davidson ‚Pro Relationale Datenbank-Design und Implementierung‘, können Sie es schaffen

CREATE SCHEMA tools 
go 
CREATE TABLE tools.sequence 
(
i int CONSTRAINT PKtools_sequence PRIMARY KEY 
) 

-- Then I will load it, up to 99999: 
;WITH DIGITS (i) as(--set up a set of numbers from 0-9 
SELECT i 
FROM (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) as digits (i)) 
--builds a table from 0 to 99999 
,sequence (i) as (
SELECT D1.i + (10*D2.i) + (100*D3.i) + (1000*D4.i) + (10000*D5.i) 
--+ (100000*D6.i) 
FROM digits AS D1 CROSS JOIN digits AS D2 CROSS JOIN digits AS D3 
CROSS JOIN digits AS D4 CROSS JOIN digits AS D5 
/* CROSS JOIN digits AS D6 */) 
INSERT INTO tools.sequence(i) 
SELECT i 
FROM sequence 

dann Ihre Eingabe aufgespalten, wieder Code von L. Davidson Buch

DECLARE @delimitedList VARCHAR(100) = '1,2,3,4,5' 
SELECT word = SUBSTRING(',' + @delimitedList + ',',i + 1, 
CHARINDEX(',',',' + @delimitedList + ',',i + 1) - i - 1) 
FROM tools.sequence 
WHERE i >= 1 
AND i < LEN(',' + @delimitedList + ',') - 1 
AND SUBSTRING(',' + @delimitedList + ',', i, 1) = ',' 
ORDER BY i 

einen Raum mit eher als ein Komma .

Schließlich würde ich den PIVOT-Operator verwenden, um die Zeilen in Spalten zu verwandeln, aber damit es funktioniert, müssen Sie die maximale Anzahl der Wörter angeben.

Verwandte Themen