„Wszystkie rekordy mają format„ Imię Nazwisko ”(bez cudzysłowów i spacji pomiędzy).” ... cudownie ... Proszę, proszę , nie zapominaj o takich ludziach jak ja przy podejmowaniu decyzji dotyczących bazy danych. Zbyt często dostaję strony internetowe, które mówią mi, że moje nazwisko zawiera niedozwolony (sic) znak ... :(
Stijn de Witt
@StijndeWitt Generalnie masz rację, jednak wygląda na to, że ta baza danych nie zawiera Twojego nazwiska, przynajmniej nie w swojej oficjalnej formie. W moim kraju nazwiska są zapisywane jako pierwsze, więc ja również byłbym „dyskryminowany” w tej tabeli danych. Zobacz to ->
Dávid Horváth,
Odpowiedzi:
226
Niestety MySQL nie posiada funkcji podziału łańcucha. Możesz jednak utworzyć w tym celu funkcję zdefiniowaną przez użytkownika, taką jak ta opisana w następującym artykule:
SELECT SPLIT_STR(membername,' ',1)as memberfirst,
SPLIT_STR(membername,' ',2)as memberlast
FROM users;
Jeśli wolisz nie używać funkcji zdefiniowanej przez użytkownika i nie masz nic przeciwko, aby zapytanie było nieco bardziej szczegółowe, możesz również wykonać następujące czynności:
nadal nie możesz użyć IN jako „tablicy wartości” z tej operacji podziału?
Miguel
3
Czy korzystanie z LENGTHwielobajtów jest bezpieczne? „LENGTH (str): Zwraca długość ciągu znaków mierzoną w bajtach. Znak wielobajtowy jest liczony jako wiele bajtów. Oznacza to, że dla ciągu zawierającego pięć znaków 2-bajtowych LENGTH () zwraca 10, natomiast CHAR_LENGTH () zwraca 5. "
Erk
Jak wspomniał @Erk, nie będzie to działać poprawnie w przypadku znaków wielobajtowych / utf8. Tylko proste rozwiązanie z dwoma instrukcjami SUBSTRING_INDEX działa z utf8 / multibyte
Michael
LENGTH (), LOCATE () lub cokolwiek, co zależy od liczby pozycji, zakończy się niepowodzeniem ze znakami wielobajtowymi.
Michael
68
Wariant SELECT (bez tworzenia funkcji zdefiniowanej przez użytkownika):
Przydatne byłoby również zobaczenie, jak odciąć tylko ostatnie słowo dla nazwiska i wszystkie inne niż ostatnie dla imienia, na przykład: Mary A. Smith, czyli typy, z którymi mam do czynienia w starej tabeli db naprawić. Zobaczę, czy uda mi się to rozgryźć i opublikuję wynik, jeśli nie, czy możesz również opublikować tę opcję, aby Twoja odpowiedź była kompletna.
Lizardx
jak możemy rzutować to na liczbę całkowitą, skoro nazwa_członka to varchar .. niech memberfirst będzie typu int. Czy zadziała, jeśli bezpośrednio użyję cast ()?
infinitywarior
Pan zasługuje na medal.
rpajaziti
23
Wydaje się, że istniejące odpowiedzi są zbyt skomplikowane lub nie stanowią ścisłej odpowiedzi na dane pytanie.
Myślę, że w tej konkretnej sytuacji nie jest konieczne zajmowanie się nazwami składającymi się z więcej niż dwóch słów. Jeśli chcesz to zrobić poprawnie, w niektórych przypadkach rozłupywanie może być bardzo trudne lub nawet niemożliwe:
Johann Sebastian Bach
Johann Wolfgang von Goethe
Edgar Allan Poe
Jakob Ludwig Felix Mendelssohn-Bartholdy
Petőfi Sándor
澤黒明
W odpowiednio zaprojektowanej bazie danych nazwiska ludzkie powinny być przechowywane zarówno w częściach, jak iw całości. Oczywiście nie zawsze jest to możliwe.
Jeśli plan jest zrobić to jako część zapytania, proszę nie robić (a) . Poważnie, to zabójca wydajności. Mogą wystąpić sytuacje, w których nie zależy Ci na wydajności (na przykład jednorazowe zadania migracji, aby podzielić pola, aby uzyskać lepszą wydajność w przyszłości), ale jeśli robisz to regularnie dla czegokolwiek innego niż baza danych myszy miki, marnujemy zasoby.
Jeśli kiedykolwiek będziesz musiał przetworzyć tylko część kolumny w jakiś sposób, twój projekt bazy danych jest wadliwy. Może dobrze działać w domowej książce adresowej, aplikacji z przepisami lub w dowolnej z wielu innych małych baz danych, ale nie da się jej skalować do „prawdziwych” systemów.
Przechowuj składniki nazwy w oddzielnych kolumnach. Łączenie kolumn za pomocą prostej konkatenacji (gdy potrzebujesz pełnego imienia i nazwiska) jest prawie zawsze o wiele szybsze niż dzielenie ich za pomocą wyszukiwania znakowego.
Jeśli z jakiegoś powodu nie możesz podzielić pola, przynajmniej umieść dodatkowe kolumny i użyj wyzwalacza wstawiania / aktualizowania, aby je wypełnić. Chociaż nie jest to 3NF, zagwarantuje to, że dane są nadal spójne i znacznie przyspieszy twoje zapytania. Możesz również upewnić się, że dodatkowe kolumny są pisane małymi literami (i indeksowane, jeśli ich szukasz) w tym samym czasie, aby nie musieć majstrować przy problemach ze wielkością liter.
A jeśli nie możesz nawet dodać kolumn i wyzwalaczy, pamiętaj (i uświadom swojego klienta, jeśli jest przeznaczony dla klienta), że nie jest skalowalny.
(a) Oczywiście, jeśli zamierzasz użyć tego zapytania do naprawienia schematu, tak aby nazwy były umieszczane w oddzielnych kolumnach w tabeli, a nie w zapytaniu, uważam to za prawidłowe użycie. Ale powtarzam, robienie tego w zapytaniu nie jest dobrym pomysłem.
Czasami musisz to zrobić. Potrzebuje tego w skrypcie migracji, więc nie obchodzą mnie występy.
Matthieu Napoli
@dfmiller, tak, zrobiłem, stąd moja uzasadniona i szczegółowa odpowiedź i dziękuję za zainteresowanie. Jeśli masz konkretny problem z czymś, co napisałem, wskaż to, a zobaczę, czy można to poprawić. Twój obecny komentarz jest praktycznie bezużyteczny w poprawianiu sytuacji, jeśli rzeczywiście taki był Twój zamiar. A może po prostu lubisz wyrzucać przypadkowe komentarze w sieci, trudno powiedzieć :-) Nie zgadzam się z odpowiedzią, oczywiście, dostęp subkolumnowy nie jest skalowalny i prawie zawsze jest złym pomysłem, chyba że jest używany do celów faktycznie naprawiający dostęp do kolumn.
paxdiablo
3
Pytanie brzmi, jak podzielić pojedynczą kolumnę na dwie, a następnie odpowiadasz, mówiąc „Nie rób tego”, a następnie przystępujesz do wyjaśniania, dlaczego należy je podzielić. Twój pierwszy akapit brzmi tak, jakbyś się spierał lub trzymał je w jednej kolumnie, ale pozostałe akapity mówią coś przeciwnego.
dfmiller
@dfmiller, być może źle zrozumiałem pytanie, nie jestem teraz pewien, czy separacja miała być dokonana w zapytaniu, czy w tabeli. Wyjaśniłem odpowiedź, miejmy nadzieję, że będzie jaśniejsza.
paxdiablo
Dużo lepiej. Nigdy nie rozważałem używania zapytania wybierającego z wyjątkiem aktualizacji bazy danych. To byłby okropny pomysł.
dfmiller
7
Użyj tego
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(`membername`,' ',2),' ',1)AS b,
SUBSTRING_INDEX(SUBSTRING_INDEX(`membername`,' ',-1),' ',2)AS c FROM`users`WHERE`userid`='1'
Spowoduje to pobranie pierwszego i ostatniego podciągu rozdzielanego spacjami z pola, co nie działa w każdych okolicznościach. Na przykład, jeśli pole nazwiska to „Lilly von Schtupp”, otrzymasz „Lilly”, „Schtupp” jako imię i nazwisko.
John Franklin,
5
Nie do końca odpowiadając na pytanie, ale napotkałem ten sam problem, który skończyłem:
UPDATE people_exit SET last_name = SUBSTRING_INDEX(fullname,' ',-1)UPDATE people_exit SET middle_name = TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(fullname,last_name,1),' ',-2))UPDATE people_exit SET middle_name =''WHERE CHAR_LENGTH(middle_name)>3UPDATE people_exit SET first_name = SUBSTRING_INDEX(fullname,concat(middle_name,' ',last_name),1)UPDATE people_exit SET first_name = middle_name WHERE first_name =''UPDATE people_exit SET middle_name =''WHERE first_name = middle_name
Jedynym przypadkiem, w którym możesz chcieć takiej funkcji, jest zapytanie UPDATE, które zmieni tabelę tak, aby przechowywała Imię i Nazwisko w oddzielnych polach.
Projekt bazy danych musi przestrzegać pewnych reguł, a normalizacja bazy danych jest jedną z najważniejszych
Niepotrzebny komentarz, ponieważ właśnie o to prosił plakat; również niedokładne, ponieważ istnieje milion razy, gdy trzeba będzie podzielić ciąg w celu uzyskania najlepszej normalizacji. Nie wiem, dlaczego ani jak to kiedykolwiek zostało przegłosowane.
daticon
Używanie indeksów na podzielonych polach jest prawie tak niemożliwe, jak przekształcenie MySQL w mulczera do liści, ale to nie powstrzyma ludzi przed pytaniem o to. Dobra odpowiedź - baza danych POWINNA odzwierciedlać dane, a nie specyfikacje rozdrabniacza do liści.
HoldOffHunger,
2
Miałem kolumnę, w której imię i nazwisko znajdowały się w jednej kolumnie. Imię i nazwisko oddzielone przecinkiem. Poniższy kod zadziałał. NIE ma sprawdzania / korygowania błędów. Tylko głupi rozłam. Użył phpMyAdmin do wykonania instrukcji SQL.
UPDATE tblAuthorList SET AuthorFirst = SUBSTRING_INDEX(AuthorLast,',',-1), AuthorLast = SUBSTRING_INDEX(AuthorLast,',',1);
To pobiera smhg stąd i curt's z ostatniego indeksu danego podciągu w MySQL i łączy je. To jest dla mysql, wszystko, czego potrzebowałem, to uzyskać porządny podział imienia na imię i nazwisko nazwisko z nazwiskiem jedno słowo, imię wszystko przed tym pojedynczym słowem, gdzie nazwa mogłaby być pusta, 1 słowo, 2 słowa lub więcej niż 2 słowa. Tj .: Null; Mary; Mary Smith; Mary A. Smith; Mary Sue Ellen Smith;
Więc jeśli nazwa to jedno słowo lub null, last_name ma wartość null. Jeśli imie jest> 1 słowo, last_name to ostatnie słowo, a first_name to wszystkie słowa przed ostatnim słowem.
Zauważ, że już usunąłem takie rzeczy jak Joe Smith Jr.; Joe Smith Esq. i tak dalej, ręcznie, co było oczywiście bolesne, ale było wystarczająco małe, aby to zrobić, więc przed podjęciem decyzji, której metody użyć, warto sprawdzić dane w polu nazwy.
Zauważ, że to również przycina wynik, więc nie kończysz ze spacjami przed lub po nazwach.
Po prostu publikuję to dla innych, którzy mogą tu znaleźć w Google, szukając tego, czego potrzebowałem. To oczywiście działa, najpierw przetestuj go z zaznaczeniem.
To jednorazowa sprawa, więc nie obchodzi mnie wydajność.
Metoda, której użyłem do podzielenia first_name na first_name i last_name, gdy dane dotarły do pola first_name. Spowoduje to umieszczenie tylko ostatniego słowa w polu nazwiska, więc „john phillips sousa” będzie oznaczać „john phillips” imię i „sousa” nazwisko. Pozwala to również uniknąć nadpisywania rekordów, które zostały już naprawione.
set last_name=trim(SUBSTRING_INDEX(first_name,' ',-1)), first_name=trim(SUBSTRING(first_name,1,length(first_name)- length(SUBSTRING_INDEX(first_name,' ',-1))))where list_id='$List_ID'and length(first_name)>0and length(trim(last_name))=0
Czy możesz podać link do dokumentacji. Wyszukiwanie dev.mysql.com wysycha. Sekcja 12.5 zawiera sugestie społeczności w komentarzach dotyczących tej funkcji.
Odpowiedzi:
Niestety MySQL nie posiada funkcji podziału łańcucha. Możesz jednak utworzyć w tym celu funkcję zdefiniowaną przez użytkownika, taką jak ta opisana w następującym artykule:
Dzięki tej funkcji:
możesz zbudować zapytanie w następujący sposób:
Jeśli wolisz nie używać funkcji zdefiniowanej przez użytkownika i nie masz nic przeciwko, aby zapytanie było nieco bardziej szczegółowe, możesz również wykonać następujące czynności:
źródło
LENGTH
wielobajtów jest bezpieczne? „LENGTH (str): Zwraca długość ciągu znaków mierzoną w bajtach. Znak wielobajtowy jest liczony jako wiele bajtów. Oznacza to, że dla ciągu zawierającego pięć znaków 2-bajtowych LENGTH () zwraca 10, natomiast CHAR_LENGTH () zwraca 5. "Wariant SELECT (bez tworzenia funkcji zdefiniowanej przez użytkownika):
Takie podejście dba również o:
Wersja UPDATE to:
źródło
Wydaje się, że istniejące odpowiedzi są zbyt skomplikowane lub nie stanowią ścisłej odpowiedzi na dane pytanie.
Myślę, że prosta odpowiedź brzmi:
Myślę, że w tej konkretnej sytuacji nie jest konieczne zajmowanie się nazwami składającymi się z więcej niż dwóch słów. Jeśli chcesz to zrobić poprawnie, w niektórych przypadkach rozłupywanie może być bardzo trudne lub nawet niemożliwe:
W odpowiednio zaprojektowanej bazie danych nazwiska ludzkie powinny być przechowywane zarówno w częściach, jak iw całości. Oczywiście nie zawsze jest to możliwe.
źródło
Jeśli plan jest zrobić to jako część zapytania, proszę nie robić (a) . Poważnie, to zabójca wydajności. Mogą wystąpić sytuacje, w których nie zależy Ci na wydajności (na przykład jednorazowe zadania migracji, aby podzielić pola, aby uzyskać lepszą wydajność w przyszłości), ale jeśli robisz to regularnie dla czegokolwiek innego niż baza danych myszy miki, marnujemy zasoby.
Jeśli kiedykolwiek będziesz musiał przetworzyć tylko część kolumny w jakiś sposób, twój projekt bazy danych jest wadliwy. Może dobrze działać w domowej książce adresowej, aplikacji z przepisami lub w dowolnej z wielu innych małych baz danych, ale nie da się jej skalować do „prawdziwych” systemów.
Przechowuj składniki nazwy w oddzielnych kolumnach. Łączenie kolumn za pomocą prostej konkatenacji (gdy potrzebujesz pełnego imienia i nazwiska) jest prawie zawsze o wiele szybsze niż dzielenie ich za pomocą wyszukiwania znakowego.
Jeśli z jakiegoś powodu nie możesz podzielić pola, przynajmniej umieść dodatkowe kolumny i użyj wyzwalacza wstawiania / aktualizowania, aby je wypełnić. Chociaż nie jest to 3NF, zagwarantuje to, że dane są nadal spójne i znacznie przyspieszy twoje zapytania. Możesz również upewnić się, że dodatkowe kolumny są pisane małymi literami (i indeksowane, jeśli ich szukasz) w tym samym czasie, aby nie musieć majstrować przy problemach ze wielkością liter.
A jeśli nie możesz nawet dodać kolumn i wyzwalaczy, pamiętaj (i uświadom swojego klienta, jeśli jest przeznaczony dla klienta), że nie jest skalowalny.
(a) Oczywiście, jeśli zamierzasz użyć tego zapytania do naprawienia schematu, tak aby nazwy były umieszczane w oddzielnych kolumnach w tabeli, a nie w zapytaniu, uważam to za prawidłowe użycie. Ale powtarzam, robienie tego w zapytaniu nie jest dobrym pomysłem.
źródło
Użyj tego
źródło
Nie do końca odpowiadając na pytanie, ale napotkałem ten sam problem, który skończyłem:
źródło
W MySQL działa ta opcja:
źródło
Jedynym przypadkiem, w którym możesz chcieć takiej funkcji, jest zapytanie UPDATE, które zmieni tabelę tak, aby przechowywała Imię i Nazwisko w oddzielnych polach.
Projekt bazy danych musi przestrzegać pewnych reguł, a normalizacja bazy danych jest jedną z najważniejszych
źródło
Miałem kolumnę, w której imię i nazwisko znajdowały się w jednej kolumnie. Imię i nazwisko oddzielone przecinkiem. Poniższy kod zadziałał. NIE ma sprawdzania / korygowania błędów. Tylko głupi rozłam. Użył phpMyAdmin do wykonania instrukcji SQL.
13.2.10 Składnia UPDATE
źródło
To pobiera smhg stąd i curt's z ostatniego indeksu danego podciągu w MySQL i łączy je. To jest dla mysql, wszystko, czego potrzebowałem, to uzyskać porządny podział imienia na imię i nazwisko nazwisko z nazwiskiem jedno słowo, imię wszystko przed tym pojedynczym słowem, gdzie nazwa mogłaby być pusta, 1 słowo, 2 słowa lub więcej niż 2 słowa. Tj .: Null; Mary; Mary Smith; Mary A. Smith; Mary Sue Ellen Smith;
Więc jeśli nazwa to jedno słowo lub null, last_name ma wartość null. Jeśli imie jest> 1 słowo, last_name to ostatnie słowo, a first_name to wszystkie słowa przed ostatnim słowem.
Zauważ, że już usunąłem takie rzeczy jak Joe Smith Jr.; Joe Smith Esq. i tak dalej, ręcznie, co było oczywiście bolesne, ale było wystarczająco małe, aby to zrobić, więc przed podjęciem decyzji, której metody użyć, warto sprawdzić dane w polu nazwy.
Zauważ, że to również przycina wynik, więc nie kończysz ze spacjami przed lub po nazwach.
Po prostu publikuję to dla innych, którzy mogą tu znaleźć w Google, szukając tego, czego potrzebowałem. To oczywiście działa, najpierw przetestuj go z zaznaczeniem.
To jednorazowa sprawa, więc nie obchodzi mnie wydajność.
źródło
Metoda, której użyłem do podzielenia first_name na first_name i last_name, gdy dane dotarły do pola first_name. Spowoduje to umieszczenie tylko ostatniego słowa w polu nazwiska, więc „john phillips sousa” będzie oznaczać „john phillips” imię i „sousa” nazwisko. Pozwala to również uniknąć nadpisywania rekordów, które zostały już naprawione.
źródło
źródło
mysql 5.4 zapewnia natywną funkcję podziału:
źródło