Database
 sql >> Baza danych >  >> RDS >> Database

Jak analizować ciągi jak profesjonalista za pomocą funkcji SQL SUBSTRING()?

Czy lubisz analizować ciągi? Jeśli tak, jedną z niezbędnych funkcji łańcuchowych do użycia jest SQL SUBSTRING. Jest to jedna z tych umiejętności, które programista powinien posiadać w każdym języku.

Więc jak to robisz?

Ważne punkty w analizie ciągów

Załóżmy, że dopiero zaczynasz analizować. O jakich ważnych punktach musisz pamiętać?

  1. Wiedz, jakie informacje są osadzone w ciągu.
  2. Uzyskaj dokładne pozycje każdej informacji w ciągu. Być może będziesz musiał policzyć wszystkie znaki w ciągu.
  3. Poznaj rozmiar lub długość każdego fragmentu informacji w ciągu.
  4. Użyj odpowiedniej funkcji ciągu, która może łatwo wyodrębnić każdą informację z ciągu.

Znajomość wszystkich tych czynników przygotuje Cię do używania SQL SUBSTRING() i przekazywania do niego argumentów.

Składnia SQL SUBSTRING

Składnia SQL SUBSTRING jest następująca:

SUBSTRING(wyrażenie ciągu, początek, długość)

  • wyrażenie tekstowe – a literał ciągu lub wyrażenie SQL, które zwraca ciąg.
  • rozpocznij – liczba, od której rozpocznie się ekstrakcja. Jest również oparty na 1 – pierwszy znak w argumencie wyrażenia łańcuchowego musi zaczynać się od 1, a nie od 0. W SQL Server zawsze jest to liczba dodatnia. Jednak w MySQL lub Oracle może być dodatnia lub ujemna. Jeśli jest ujemny, skanowanie rozpoczyna się od końca ciągu.
  • długość – długość znaków do wyodrębnienia. SQL Server tego wymaga. W MySQL lub Oracle jest to opcjonalne.

4 przykłady SQL SUBSTRING

1. Używanie SQL SUBSTRING do wyodrębniania z literału ciągu

Zacznijmy od prostego przykładu z dosłownym ciągiem. Używamy nazwy słynnej koreańskiej grupy dziewcząt, BlackPink, a Rysunek 1 ilustruje, jak będzie działać SUBSTRING:

Poniższy kod pokazuje, jak go wyodrębnimy:

-- extract 'black' from BlackPink (English)
SELECT SUBSTRING('BlackPink',1,5) AS result

Teraz przyjrzyjmy się również zestawowi wyników na rysunku 2:

Czy to nie łatwe?

Aby wyodrębnić Czarny od Czarnoróżowy , zaczynasz od pozycji 1, a kończysz na pozycji 5. Od BlackPink jest koreański, dowiedzmy się, czy SUBSTRING działa na koreańskich znakach Unicode.

(ZASTRZEŻENIE :Nie umiem mówić, czytać ani pisać po koreańsku, więc dostałem koreańskie tłumaczenie z Wikipedii. Użyłem także Tłumacza Google, aby zobaczyć, które znaki odpowiadają Czarnemu i różowy . Proszę wybacz mi, jeśli to źle. Mam jednak nadzieję, że nadejdzie kwestia, którą staram się wyjaśnić w poprzek)

Zróbmy napis w języku koreańskim (patrz rysunek 3). Użyte znaki koreańskie przekładają się na BlackPink:

Teraz zobacz poniższy kod. Wyodrębnimy dwa znaki odpowiadające Czarnemu .

-- extract 'black' from BlackPink (Korean)
SELECT SUBSTRING(N'블랙핑크',1,2) AS result

Czy zauważyłeś koreański ciąg poprzedzony przez N ? Używa znaków Unicode, a SQL Server przyjmuje NVARCHAR i powinien być poprzedzony przez N . To jedyna różnica w wersji angielskiej. Ale czy będzie działać dobrze? Zobacz rysunek 4:

Działał bez błędów.

2. Używanie SQL SUBSTRING w MySQL z ujemnym argumentem startowym

Posiadanie ujemnego argumentu start nie zadziała w SQL Server. Ale możemy mieć tego przykład przy użyciu MySQL. Tym razem wyodrębnijmy różowy od Czarnoróżowy . Oto kod:

-- Extract 'Pink' from BlackPink using MySQL Substring (English)
select substring('BlackPink',-4,4) as result;

Teraz przyjrzyjmy się wynikowi na rysunku 5:

Ponieważ przekazaliśmy -4 do parametru start, wyodrębnianie rozpoczęło się od końca łańcucha, cofając się o 4 znaki. Aby osiągnąć ten sam wynik w SQL Server, użyj funkcji RIGHT().

Znaki Unicode działają również z MySQL SUBSTRING, jak widać na rysunku 6:

Działało dobrze. Ale czy zauważyłeś, że nie musimy poprzedzać ciągu N? Zauważ też, że istnieje kilka sposobów na uzyskanie podciągu w MySQL. Widziałeś już SUBSTRING. Równoważnymi funkcjami w MySQL są SUBSTR() i MID().

3. Parsowanie podciągów za pomocą argumentów o zmiennym początku i długości

Niestety nie wszystkie wyciągi ciągów używają stałych argumentów początku i długości. W takim przypadku potrzebujesz CHARINDEX, aby uzyskać pozycję ciągu, na który kierujesz. Spójrzmy na przykład:

DECLARE @lineString NVARCHAR(30) = N'김제니 01/16/[email protected]'
DECLARE @name NVARCHAR(5)
DECLARE @bday DATE
DECLARE @instagram VARCHAR(20)

SET @name = SUBSTRING(@lineString,1,CHARINDEX('@',@lineString)-11)
SET @bday = SUBSTRING(@lineString,CHARINDEX('@',@lineString)-10,10)
SET @instagram = SUBSTRING(@lineString,CHARINDEX('@',@lineString),30)

SELECT @name AS [Name], @bday AS [BirthDate], @instagram AS [InstagramAccount]

W powyższym kodzie musisz wyodrębnić imię i nazwisko w języku koreańskim, datę urodzenia i konto na Instagramie.

Zaczynamy od zdefiniowania trzech zmiennych do przechowywania tych informacji. Następnie możemy przeanalizować ciąg i przypisać wyniki do każdej zmiennej.

Możesz pomyśleć, że posiadanie ustalonych startów i długości jest prostsze. Poza tym możemy to namierzyć, przeliczając znaki ręcznie. Ale co, jeśli masz ich dużo na stole?

Oto nasza analiza:

  • Jedynym stałym elementem w ciągu jest @ postaci na koncie na Instagramie. Możemy określić jego pozycję w łańcuchu za pomocą CHARINDEX. Następnie używamy tej pozycji, aby uzyskać początek i długość reszty.
  • Data urodzenia jest w ustalonym formacie MM/dd/rrrr z 10 znakami.
  • Aby wyodrębnić imię, zaczynamy od 1. Ponieważ data urodzenia ma 10 znaków plus @ znak, możesz dostać się do końcowego znaku nazwy w ciągu. Z pozycji @ postać, cofamy się o 11 znaków. SUBSTRING(@lineString,1,CHARINDEX(‘@’,@lineString)-11) to droga do zrobienia.
  • Aby uzyskać datę urodzin, stosujemy tę samą logikę. Uzyskaj pozycję @ znak i przesuń 10 znaków wstecz, aby uzyskać wartość początkową daty urodzenia. 10 to stała długość. SUBSTRING(@lineString,CHARINDEX(‘@’,@lineString)-10,10) jak uzyskać datę urodzin.
  • Wreszcie uzyskanie konta na Instagramie jest proste. Zacznij od pozycji @ znak za pomocą CHARINDEX. Uwaga:30 to limit nazw użytkowników na Instagramie.

Sprawdź wyniki na rysunku 7:

4. Używanie SQL SUBSTRING w instrukcji SELECT

Możesz również użyć SUBSTRING w instrukcji SELECT, ale najpierw musimy mieć dane robocze. Oto kod:

SELECT
 CAST(P.LastName AS CHAR(50)) 
 + CAST(P.FirstName AS CHAR(50)) 
 + CAST(ISNULL(P.MiddleName,'') AS CHAR(50)) 
 + CAST(ea.EmailAddress AS CHAR(50)) 
 + CAST(a.City AS CHAR(30)) 
 + CAST(a.PostalCode AS CHAR(15)) AS line
INTO PersonContacts
FROM Person.Person p
INNER JOIN Person.EmailAddress ea 
  ON P.BusinessEntityID = ea.BusinessEntityID
INNER JOIN Person.BusinessEntityAddress bea 
  ON P.BusinessEntityID = bea.BusinessEntityID
INNER JOIN Person.Address a 
  ON bea.AddressID = a.AddressID

Powyższy kod tworzy długi ciąg zawierający imię i nazwisko, adres e-mail, miasto i kod pocztowy. Chcemy go również przechowywać w PersonelContacts tabela.

Teraz zajmijmy się kodem do inżynierii wstecznej za pomocą SUBSTRING:

SELECT
 TRIM(SUBSTRING(line,1,50)) AS [LastName]
,TRIM(SUBSTRING(line,51,50)) AS [FirstName]
,TRIM(SUBSTRING(line,101,50)) AS [MiddleName]
,TRIM(SUBSTRING(line,151,50)) AS [EmailAddress]
,TRIM(SUBSTRING(line,201,30)) AS [City]
,TRIM(SUBSTRING(line,231,15)) AS [PostalCode]
FROM PersonContacts pc
ORDER BY LastName, FirstName

Ponieważ użyliśmy kolumn o stałym rozmiarze, nie ma potrzeby używania CHARINDEX.

Używanie SQL SUBSTRING w klauzuli WHERE – pułapka wydajności?

To prawda. Nikt nie może powstrzymać Cię przed użyciem SUBSTRING w klauzuli WHERE. Jest to poprawna składnia. Ale co, jeśli spowoduje to problemy z wydajnością?

Dlatego udowadniamy to na przykładzie, a następnie omawiamy, jak rozwiązać ten problem. Ale najpierw przygotujmy nasze dane:

USE AdventureWorks
GO

SELECT * INTO SalesOrders FROM Sales.SalesOrderHeader soh

Nie mogę zepsuć SalesOrderHeader stół, więc zrzuciłem go na inny stół. Następnie utworzyłem SalesOrderID w nowych Zamówieniach sprzedaży podaj klucz podstawowy.

Teraz jesteśmy gotowi na zapytanie. Używam dbForge Studio dla SQL Server z trybem profilowania zapytań WŁĄCZONYM do analizy zapytań.

SELECT
 so.SalesOrderID
,so.OrderDate
,so.CustomerID
,so.AccountNumber
FROM SalesOrders so
WHERE SUBSTRING(so.AccountNumber,4,4) = '4030'

Jak widać, powyższe zapytanie działa poprawnie. Teraz spójrz na diagram profilu zapytania na rysunku 8:

Diagram planu wygląda na prosty, ale przyjrzyjmy się właściwościom węzła Clustered Index Scan. W szczególności potrzebujemy informacji o czasie wykonywania:

Ilustracja 9 przedstawia strony 785 * 8 KB odczytane przez silnik bazy danych. Zauważ również, że rzeczywisty odczyt wierszy to 31 411. Jest to łączna liczba wierszy w tabeli. Jednak zapytanie zwróciło tylko 27 605 rzeczywistych wierszy.

Cała tabela została odczytana przy użyciu indeksu klastrowego jako odniesienia.

Dlaczego?

Chodzi o to, że serwer SQL musi wiedzieć, czy 4030 jest podciągiem numeru Konta. Musi czytać i oceniać każdy zapis. Odrzuć wiersze, które nie są równe i zwróć potrzebne wiersze. Wykonuje zadanie, ale nie wystarczająco szybko.

Co możemy zrobić, aby działał szybciej?

Unikaj SUBSTRING w klauzuli WHERE i uzyskaj ten sam wynik szybciej

Teraz chcemy uzyskać ten sam wynik bez użycia SUBSTRING w klauzuli WHERE. Wykonaj poniższe czynności:

  • Zmień tabelę, dodając kolumnę obliczaną z SUBSTRING(numer konta, 4,4) formuła. Nazwijmy go AccountCategory z braku lepszego terminu.
  • Utwórz indeks nieklastrowy dla nowej AccountCategory kolumna. Uwzględnij datę zamówienia , Numer Konta i ID klienta kolumny.

To wszystko.

Zmieniamy klauzulę WHERE zapytania, aby dostosować nową AccountCategory kolumna:

SET STATISTICS IO ON

SELECT
 so.SalesOrderID
,so.OrderDate
,so.CustomerID
,so.AccountNumber
FROM SalesOrders so
WHERE so.AccountCategory = '4030'

SET STATISTICS IO OFF

W klauzuli WHERE nie ma SUBSTRING. Sprawdźmy teraz diagram planu:

Skanowanie indeksu zostało zastąpione przez wyszukiwanie indeksu. Zauważ również, że SQL Server użył nowego indeksu w wyliczonej kolumnie. Czy nastąpiły również zmiany w odczytach logicznych i rzeczywistych odczytanych wierszach? Zobacz rysunek 11:

Zmniejszenie z 785 do 222 odczytów logicznych to wielka poprawa, ponad trzy razy mniej niż oryginalne odczyty logiczne. Zminimalizowało również rzeczywisty odczyt wierszy tylko do tych wierszy, których potrzebujemy.

Dlatego użycie SUBSTRING w klauzuli WHERE nie jest dobre dla wydajności i dotyczy każdej innej funkcji o wartościach skalarnych używanej w klauzuli WHERE.

Wniosek

  • Programiści nie mogą uniknąć analizowania ciągów. Taka potrzeba pojawi się w taki czy inny sposób.
  • Podczas analizowania ciągów niezbędne jest poznanie informacji w ciągu, pozycji każdej części informacji oraz ich rozmiarów lub długości.
  • Jedną z funkcji analizujących jest SQL SUBSTRING. Potrzebuje tylko ciągu do przeanalizowania, pozycji do rozpoczęcia ekstrakcji i długości ciągu do wyodrębnienia.
  • SUBSTRING może mieć różne zachowania między smakami SQL, takimi jak SQL Server, MySQL i Oracle.
  • Możesz użyć SUBSTRING z literałowymi ciągami i ciągami w kolumnach tabeli.
  • Użyliśmy również SUBSTRING ze znakami Unicode.
  • Użycie SUBSTRING lub dowolnej funkcji o wartościach skalarnych w klauzuli WHERE może zmniejszyć wydajność zapytania. Napraw to za pomocą indeksowanej kolumny obliczeniowej.

Jeśli uznasz ten post za pomocny, udostępnij go na preferowanych platformach społecznościowych lub udostępnij swój komentarz poniżej?


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Anatomia roli programisty:analityk danych

  2. Polecenia SQL

  3. Wprowadzenie do TimescaleDB

  4. Lepiej ALTER niż DROP

  5. UŻYJ PODPOWIEDZI i DISABLE_OPTIMIZED_NESTED_LOOP