Der Operator LIKE
ist langsam und wird etwas langsam sein, sobald Sie ein paar hunderttausend Datensätze getroffen haben. Diese Antwort ist nicht super schnell, aber wird die Aufgabe erledigen und erfordert keine SQL Server CLR. Wenn das gewählte System Oracle ist, benötigen Sie 11g, um die gleiche Syntax zu verwenden.
Sie haben eine Tabelle der Annahme ...
create table udata (
ID int primary key identity(1,1)
, string varchar(2000) not null
);
Sie werden eine Variable für diese für zukünftige Änderungen wollen, sondern auch für Skript Flexibilität.
declare @delimiter varchar(1) = '|'
Dann alles in einem CTE einrichten.
;with parser as (
select
ID
, 0 as colNum
, substring(d.string, endPos + (2 * delimLen), len(d.string)) as string
, startPos
, endPos
from udata d
cross apply (
select
len(@delimiter) as startPos
, case charindex(@delimiter,d.string) when 0 then len(d.string) + len(@delimiter) else charindex(@delimiter,d.string) end - len(@delimiter) as endPos
, len(@delimiter) as delimLen
) p
where id between 2000 and 10000
union all
select
ID
, colNum + 1 as colNum
, substring(d.string, p.endPos + (2 * delimLen), len(d.string)) as string
, d.endPos + (2 * delimLen) as startPos
, d.endPos + (delimLen) + p.endPos as endPos
from parser d
cross apply (
select
len(@delimiter) as startPos
, case charindex(@delimiter,d.string) when 0 then len(d.string) + len(@delimiter) else charindex(@delimiter,d.string) end - len(@delimiter) as endPos
, len(@delimiter) as delimLen
) p
where string != ''
), selector as (
select u.id, p.colNum, substring(u.string, p.startPos, p.endPos - p.startPos + len(@delimiter)) as colVal--,u.string, p.startPos, p.endPos
from udata u
inner join parser p
on p.ID = u.ID
)
Was dies bedeutet ist, markieren Sie zunächst die Standorte für den Beginn und das Ende jeder Spalte Wert, dann werden die Wähler Scheiben es aus dem Quellstring. Beachten Sie die Where-Klausel im ersten Teil der rekursiven Abfrage: where id between 2000 and 10000
Sie möchten hier Ihre Datensätze begrenzen. Dies könnte sein, wo Sie es auf die Arten von Datensätzen beschränken, nach denen Sie suchen.
Schließlich wählen Sie Ihre Spalten in einer Pivot für eine einfache Lesung aus:
select *
from selector
pivot (
max(colVal) for colNum in ([1],[2],[3],[4],[5],[6],[7],[8])
) pv
Die ursprünglichen Zeilen stattdessen zurückgegeben werden können Ihre ursprünglichen Kriterien wie folgt aus:
select *
from udata u
where exists (
select top 1 1
from selector s
where s.colNum = 5
and s.colVal =''
and s.ID = u.ID
)
Meine Testdaten enthält ~ 160.000 Zeilen, und die Abfrage existiert, ohne die ID-Grenzen in der CTE, dauerte 18 Sekunden auf Laptop-Hardware ausgeführt werden. Trotzdem sollte das den Trick machen.
Welche DBMS verwenden Sie? Postgres? Orakel? –
Warum werden diese Daten nicht zuerst in eine richtige Tabelle geladen? Warum eine Zeichenkette speichern? Haben Sie Einfluss darauf? –
Nein, ich habe keinen Einfluss darauf. –