zapytań SQL (BY)

głosy
1

Chcę wymienić (posortowaną listę) wszystkie moje wpisy z atrybutów zwany streetNames w moich klientów stół / relacji. na przykład. Chcę osiągnąć w następującej kolejności:

Street_1A
Street_1B
Street_2A
Street_2B
Street_12A
Street_12B

Prosty zamówienie przez streetNames zrobi leksykalny porównania, a następnie Street_12A i B przyjdzie przed Street_2A / B, a to nie jest poprawne. Czy jest możliwe, aby rozwiązać ten problem czystego SQL?

Utwórz 09/12/2008 o 16:05
źródło użytkownik
W innych językach...                            


7 odpowiedzi

głosy
2

Dla przypomnienia: to się nazywa Natural Sort Order , a tam jest Coding Horror artykuł na ten temat.

Myślę, że można to zrobić w SQL przy użyciu niektórych kodu pokazał tutaj, ale będzie od zawsze w przypadku przez scenariuszu.

Odpowiedział 09/12/2008 o 17:11
źródło użytkownik

głosy
2

Wybierz street_name z Tablex zamówienia przez udf_getStreetNumber (street_name)

w udf_getStreetNumber - wyraź swoją regułę biznesową do odpędzania się numer

EDYTOWAĆ

Myślę, że można użyć regex funkcje w SQL Server teraz. Chciałbym po prostu rozebrać wszystkie znaki inne niż numer z wejścia.

Odpowiedział 09/12/2008 o 16:10
źródło użytkownik

głosy
1

Jeśli masz zapisem dostęp do bazy danych będzie naprawdę polecam konwersji to wszystkich do korzystania z 3 oddzielnych pól, a następnie stosując je w odpowiedni sposób. W ten sposób można nawet zrobić to w PHP (tak, to zajmie trochę czasu, ale stanie się to tylko raz). Może to być jakiś ból, jeśli masz dużą bazę kodu, konieczności sprawdzenia wszystkich zapytań z tej tabeli, ale w końcu ulegnie pay-off później. Na przykład, sprawi, że wyszukiwanie według adresu znacznie łatwiejsze.

Odpowiedział 09/12/2008 o 16:27
źródło użytkownik

głosy
1

Jestem pewien, że można się przez podzielenie pola nazwie ulicy w to różne kawałki z czymś substr (nazwie ulicy, 1, znaleźć (””, nazwie ulicy)) tylko na ulicy i tak dalej. Ale to będzie bardzo brudny i będzie mieć do czynienia z wszelkiego rodzaju szczególnych przypadkach (bez numeru domu, numer domu bez dodatku) lub sprawach międzynarodowych (w USA, adresy są zazwyczaj podoba 1 ulicy).

Ale jeśli chcesz do sortowania, jak opisane i że jest ważnym wymogiem, byłoby lepiej dla modelu nazwie ulicy w trzech częściach, tj ulicy (np „Street”), house_number (np 1, 2, 12), house_num_addition ( na przykład "A", "B"). Następnie porządek staje się trywialny w SQL.

Odpowiedział 09/12/2008 o 16:15
źródło użytkownik

głosy
-1

Jeśli jest to przypadek, że wszystkie wartości w kolumnie streetNames śledzić przestrzeń wzorca StreetName- - StreetNumber

gdzie nazwie ulicy może zawierać inne przestrzenie, ale StreetNumber nie może, to będzie działać:

Declare @T Table (streetName VarChar(50))
Insert @T(streetName) Values('Street 1A')
Insert @T(streetName) Values('Street 2A')
Insert @T(streetName) Values('Street 2B')
Insert @T(streetName) Values('Street 12A')
Insert @T(streetName) Values('Another Street 1A')
Insert @T(streetName) Values('Another Street 4A')
Insert @T(streetName) Values('a third Street 12B')
Insert @T(streetName) Values('a third Street 1C')

Select * From @T 
Order By Substring(StreetName, 0, 1 + len(StreetName) - charIndex(' ', reverse(StreetName))),
       Cast(Substring(StreetName, 2 + len(StreetName) - charIndex(' ', reverse(StreetName)),  
        Case When IsNumeric(Substring(StreetName, 2 + len(StreetName) - charIndex(' ', reverse(StreetName)), 5)) = 1  Then 5
             When IsNumeric(Substring(StreetName, 2 + len(StreetName) - charIndex(' ', reverse(StreetName)), 4)) = 1  Then 4
             When IsNumeric(Substring(StreetName, 2 + len(StreetName) - charIndex(' ', reverse(StreetName)), 3)) = 1  Then 3
             When IsNumeric(Substring(StreetName, 2 + len(StreetName) - charIndex(' ', reverse(StreetName)), 2)) = 1  Then 2
             When IsNumeric(Substring(StreetName, 2 + len(StreetName) - charIndex(' ', reverse(StreetName)), 1)) = 1  Then 1
                End) as Integer),
        Substring(StreetName, len(StreetName) - charIndex(' ', reverse(StreetName)) +
            Case When IsNumeric(Substring(StreetName, 2 + len(StreetName) - charIndex(' ', reverse(StreetName)), 5)) = 1  Then 5
             When IsNumeric(Substring(StreetName, 2 + len(StreetName) - charIndex(' ', reverse(StreetName)), 4)) = 1  Then 6
             When IsNumeric(Substring(StreetName, 2 + len(StreetName) - charIndex(' ', reverse(StreetName)), 3)) = 1  Then 5
             When IsNumeric(Substring(StreetName, 2 + len(StreetName) - charIndex(' ', reverse(StreetName)), 2)) = 1  Then 4
             When IsNumeric(Substring(StreetName, 2 + len(StreetName) - charIndex(' ', reverse(StreetName)), 1)) = 1  Then 3
                End, Len(StreetName))
Odpowiedział 09/12/2008 o 16:35
źródło użytkownik

głosy
-1

Tak, to możliwe! Ale na pewno nie interesuje! Jeśli znajdziesz kogoś tutaj gotowy do spędzenia kilku godzin spisanie i testowania SP, który podzieli się swoimi streetNames w połączeniu nazwie ulicy + streetNumber, daj mi swoje imię: złożę mu kilka problemów, gdzie myślałem, że zapłacić, aby uzyskać Praca skończona.

Nawiasem mówiąc, nie można podzielić dane na 2 pola, jeden „nazwie ulicy” tylko z nazwy ulicy, a nowe pole „buildingNumber”? (Unikać, aby wymienić ten jeden „streetNumber”, jak w niektórych krajach / miastach, ulice są podane numery).

Odpowiedział 09/12/2008 o 16:13
źródło użytkownik

głosy
-2

Niezawodny sposób to zrobić (niezawodne w kategoriach „uporządkować swoje dane poprawnie”, a nie „aby rozwiązać swoje problemy ogólne”) jest podzielić dane na nazwę ulicy i numer domu i uporządkować zarówno z nich na własną rękę. Wymaga to jednak wiedząc, gdzie rozpoczyna się numer domu. I to jest skomplikowana część - przy założeniu najlepiej pasuje do Twoich danych.

Należy używać coś jak następuje byłaby swoje dane i odtąd sklepie numer domu w oddzielnym polu. Wszystko to string-żonglerka nie będzie wykonywać zbyt dobrze, jeśli chodzi o sortowanie dużych zestawów danych.

Zakładając, że jest to ostatnia rzecz na nazwę ulicy, a to zawiera numer:

DECLARE @test TABLE
(
  street VARCHAR(100)
)

INSERT IGNORE  INTO @test (street) VALUES('Street')
INSERT IGNORE  INTO @test (street) VALUES('Street 1A')
INSERT IGNORE  INTO @test (street) VALUES('Street1 12B')
INSERT IGNORE  INTO @test (street) VALUES('Street 22A')
INSERT IGNORE  INTO @test (street) VALUES('Street1 200B-8a')
INSERT IGNORE  INTO @test (street) VALUES('')
INSERT IGNORE  INTO @test (street) VALUES(NULL)

SELECT
  street,
  CASE 
    WHEN LEN(street) > 0 AND CHARINDEX(' ', REVERSE(street)) > 0
    THEN CASE
      WHEN RIGHT(street, CHARINDEX(' ', REVERSE(street)) - 1) LIKE '%[0-9]%'
      THEN LEFT(street, LEN(street) - CHARINDEX(' ', REVERSE(street)))
    END
  END street_part,
  CASE 
    WHEN LEN(street) > 0 AND CHARINDEX(' ', REVERSE(street)) > 0
    THEN CASE 
      WHEN RIGHT(street, CHARINDEX(' ', REVERSE(street)) - 1) LIKE '%[0-9]%'
      THEN RIGHT(street, CHARINDEX(' ', REVERSE(street)) - 1)
    END
  END house_part,
  CASE 
    WHEN LEN(street) > 0 AND CHARINDEX(' ', REVERSE(street)) > 0
    THEN CASE 
      WHEN RIGHT(street, CHARINDEX(' ', REVERSE(street)) - 1) LIKE '%[0-9]%'
      THEN CASE
        WHEN PATINDEX('%[a-z]%', LOWER(RIGHT(street, CHARINDEX(' ', REVERSE(street)) - 1))) > 0
        THEN CONVERT(INT, LEFT(RIGHT(street, CHARINDEX(' ', REVERSE(street)) - 1), PATINDEX('%[^0-9]%', LOWER(RIGHT(street, CHARINDEX(' ', REVERSE(street)) - 1))) - 1))
      END
    END
  END house_part_num
FROM
  @test 
ORDER BY
  street_part,
  house_part_num,
  house_part

Zakłada tych warunków:

  • ulica może mieć numer domu
  • liczba dom musi być ostatnią rzeczą, na adres pocztowy (nie „525 Monroe Av”).
  • numer domu powinna zaczynać się od cyfry mają być posortowane prawidłowo
  • numer domu może być zakres ( „200-205”), to byłyby klasyfikowane poniżej 200
  • numer domu nie może zawierać spacji lub uznanie nie powiedzie się (Jeśli spojrzeć na dane, można zastosować coś podobnego REPLACE(street, ' - ', '-')do dezynfekcji typowych wzorców wcześniej).
  • cała ta sprawa jest nadal przybliżeniem, że na pewno odbiega od tego, co to będzie wyglądać w książce telefonicznej, na przykład
Odpowiedział 09/12/2008 o 16:29
źródło użytkownik

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more