w jednej kolumnie mam wiersze z taką zawartością (tekst + liczby (różnej długości))
/aaaaaa/bbbbbb/cccccc/ddddddd/eeeeee
chciałbym wyżycić te dane do osobnych kolumn w jednym wierszu - separatorem jest /
jakim poleceniem to zrobić ???
w jednej kolumnie mam wiersze z taką zawartością (tekst + liczby (różnej długości))
/aaaaaa/bbbbbb/cccccc/ddddddd/eeeeee
chciałbym wyżycić te dane do osobnych kolumn w jednym wierszu - separatorem jest /
jakim poleceniem to zrobić ???
A tych separatorów też jest rózna ilość?
UPDATE
Jaka baza? Bo postgresie jest coś takiego https://www.postgresql.org/docs/15/functions-string.html
Zwłaszcza split_part i string_to_table wydają się przydatne
separatorów "/" jest 5 - stała ilość., baza MSSQL. W MSSQL próbowałem split i dzielił mi ten tekst, ale w dół - czyli zwielokrotniał ilość wierszy - a ja potrzebuje jeden wiersz i 5 kolumn.
Pytanie - o co Ci chodzi? Bo tak nie do końca zrozumiałem.
Czy masz już te dane w bazie i chcesz je przerobić na stałe, a potem pracować już na tych 5 kolumnach, czy chcesz cały czas trzymać to w jednej kolumnie, oddzielone ukośnikiem, a jedynie je rozdzielać podczas wykonywania zapytania SELECT i w postaci rozdzielonej przesłać do aplikacji?
dane w bazie mają pozostać niezmienione (mam je w bazie). Potrzebuję wyciągnąć (rozbić) je SELECT-em do 5 kolumn w celu dalszej analizy.
A serio musisz to robić po stronie bazy?
Nie byłoby lepiej i prościej, żeby pobrać sobie po jednej linii z bazy, a potem tą linie już sobie rozdzielić na 5 części w apce?
Ponad 1 milion wierszy w bazie, w excelu mało user friendly - przynajmniej jak dla mnie, ale mistrzem excela nie jestem, SQL-a również jak widać, bo nie mogę sobie z tym poradzić.
Dlatego proszę o wsparcie.
Zmienić w locie kolumne na xml i wyciągać węzły
with v as (
Select
kolumna
,convert(xml,'<r><k>'+replace(kolumna,'/','</k><k>')+'</k></r>') x
from
Tabela
)
Select
*
,x.value('/r[1]/k[2]','varchar(100)') w1
,x.value('/r[1]/k[3]','varchar(100)') w2
,x.value('/r[1]/k[4]','varchar(100)') w3
,x.value('/r[1]/k[5]','varchar(100)') w4
,x.value('/r[1]/k[6]','varchar(100)') w5
from
v
hadek napisał(a):
separatorów "/" jest 5 - stała ilość., baza MSSQL. W MSSQL próbowałem split i dzielił mi ten tekst, ale w dół - czyli zwielokrotniał ilość wierszy - a ja potrzebuje jeden wiersz i 5 kolumn.
No tak.
Każda funkcja / wyrażenie SQL, która z zasady zwraca "jedną sztukę", skalar, a jest tego w realnym życiu kilka, robi to w pionie. Taki SQL jest.
Zróbmy "reductio ad absurdum". Załóżmy, że tak super funkcja split
istnieje - to co miałaby zwracać? Nie może zwrócić pięciu skalarów, bo nie, i już.
Mogłaby (o ile by istniała) zwrócić SQL array (w serwerach, które posiadają tą koncepcję), ale to też cię nie interesuje, array to nie to samo, co piec skalarów ...
Post @Panczo (wydaje sie nadmiernie złożony) ale i tak ostatecznie co prezentuje ? Pięć wyrażeń na liście select
. Po prostu "nie chce być inaczej"
Tą samą ideę pięciu wyrażeń można inaczej zaimplementować, jako piec substringów czy coś podobnego. Inna implementacja, ta sama filozofia rozwiązania
cerrato napisał(a):
A serio musisz to robić po stronie bazy?
Nie byłoby lepiej i prościej, żeby pobrać sobie po jednej linii z bazy, a potem tą linie już sobie rozdzielić na 5 części w apce?
Dokładnie.
hadek napisał(a):
w jednej kolumnie mam wiersze z taką zawartością (tekst + liczby (różnej długości))
/aaaaaa/bbbbbb/cccccc/ddddddd/eeeeee
To teraz już wiesz, że taki projekt bazy jest d/d, i następnej tak nie zrobisz.
@ZrobieDobrze - jeśli uważasz,że w SQL nie da się tego zrealizować, to wystarczyło napisać to w jednym zdaniu.
To teraz już wiesz, że taki projekt bazy jest d/d, i następnej tak nie zrobisz
- skąd te wnioski, że to mój projekt ?
@ZrobieDobrze:
Troche słabe zaprzeczenie:
Zróbmy "reductio ad absurdum". Załóżmy, że tak super funkcja split istnieje - to co miałaby zwracać? Nie może zwrócić pięciu skalarów, bo nie, i już.
A dlaczego nie może?
CREATE FUNCTION Split(@s varchar(150))
RETURNS @scalar TABLE (
s1 VARCHAR(50),
s2 VARCHAR(50),
s3 VARCHAR(50),
s4 VARCHAR(50),
s5 VARCHAR(50)
)
AS
BEGIN
DECLARE @x xml
set @x = convert(xml,'<r><k>'+replace(@s,'/','</k><k>')+'</k></r>')
INSERT INTO @scalar
values (
@x.value('/r[1]/k[2]','varchar(100)')
,@x.value('/r[1]/k[3]','varchar(100)')
,@x.value('/r[1]/k[4]','varchar(100)')
,@x.value('/r[1]/k[5]','varchar(100)')
,@x.value('/r[1]/k[6]','varchar(100)')
)
RETURN
END;
I wtedy:
select *
from Tabela
cross apply split(Kolumna)
Mamy oczekiwany wynik "w poziomie"
Zresztą jeżeli wyjdziemy z SQL Servera:
Tak oczywiście zgodzę się z tobą, że nadal trzeba napisać pięć wyrażeń, ale nie zaprzeczaj, że takie funkcje nie istnieją.
No tak ...
W tamtym poście powinienem sobie przywołać choćby klasyczną procedurę SQL, która zwraca nie SQL array a SQL Table
Panczo napisał(a):
Tak oczywiście zgodzę się z tobą, że nadal trzeba napisać pięć wyrażeń, ale nie zaprzeczaj, że takie funkcje nie istnieją.
Pewien doktoryzując się należało postawić nie tezę "załóżmy że istnieją" a "istnieją i są przydatne w oczekiwany sposób"
ps. Nie ma innego sposobu podzielić, niż przechodząc przez XML ? Trochę strzelanie z armaty
Mam przed oczami (w dialekcie MS-SQL) Substring
w połączeniu z Charindex(...'/'..)
, doprowadzi do skutku, żmudne, mało eleganckie
@Panczo: sprawdziłem Twoją propozycję i jak robię select-a dla pierwszych 1000 wierszy to jest ok - dodatkowe kolumny się tworzą etc. Natomiast jak wykonuję to samo dla całej dabeli, to otrzymuję: Msg 9421, Level 16, State 1, Line 42
XML parsing: line 1, character 180, illegal name character
@ZrobieDobrze: można oczywiście bawić się w charindex, ale wbrew pozorom jak pojawi się coś nieoczekiwanego w parsowanym ciąg to wywali błędem i wyrażenie które będzie na to odporne będzie strasznie toporne.
W teorii można użyć string_split, ale dopiero od wersji 2022 dodali parametr który zwróci w wyniku pozycję w stringu, a tak nie ma gwarancji w jakiej kolejności to zostanie zwrócone.
@hadek jeżeli masz w tym polu któryś z tych znaków: <, >, &, ', " to musisz je zamienić https://stackoverflow.com/questions/1091945/what-characters-do-i-need-to-escape-in-xml-documents
@ZrobieDobrze: dużo pomogło, ale mam problem z "' represents ' - nie mogę wyszukać ' i potem zrobić update - pozostałe zrobiłem i jest dużo lepiej, ale wisi mi jeszcze ten znak
Replace(kolumna,'''',''')