consulta SQL (ordem por)

votos
1

Eu quero listar (a lista ordenada) todas as minhas entradas de um atributo chamado nomes de ruas em minha mesa / relação clientes. por exemplo. Eu quero alcançar a seguinte ordem:

Street_1A
Street_1B
Street_2A
Street_2B
Street_12A
Street_12B

A ordem simples por nomes de ruas vai fazer uma comparação lexical e depois Street_12A e B virá antes Street_2A / B, e que não é correto. É possível resolver isso SQL puro?

Publicado 09/12/2008 em 16:05
fonte usuário
Em outras línguas...                            


7 respostas

votos
2

Para o registro: ele é chamado Natural ordem de classificação , e há um artigo horror Coding no assunto.

Eu acho que você pode fazê-lo no SQL usando parte do código mostrado aqui, mas será por sempre em um caso de cenário.

Respondeu 09/12/2008 em 17:11
fonte usuário

votos
2

Selecione STREET_NAME da ordem tablex por udf_getStreetNumber (STREET_NAME)

em sua udf_getStreetNumber - escrever sua regra de negócios para que eliminasse o número

EDITAR

Eu acho que você pode usar a funcionalidade regex no SQL Server agora. Eu tinha acabado de retirar todos os caracteres não-número a partir da entrada.

Respondeu 09/12/2008 em 16:10
fonte usuário

votos
1

Se você tiver acesso de gravação ao banco de dados Eu realmente recomendo convertendo tudo para usar 3 campos separados e, em seguida, usá-los de forma adequada. Desta forma, você pode até mesmo fazê-lo em PHP (sim, vai demorar algum tempo, mas isso vai acontecer apenas uma vez). Este poderia ser um pouco de dor, se você tem uma grande base de código, ter que verificar para todas as consultas com esta tabela, mas acabará por pagar-off mais tarde. Por exemplo, ele vai fazer a pesquisa por endereço muito mais fácil.

Respondeu 09/12/2008 em 16:27
fonte usuário

votos
1

Tenho certeza que você poderia dividindo-se o campo da rua em que é diferentes peças com algo como substr (streetname, 1, encontrar ("", nome da rua)) apenas para a rua e assim por diante. Mas isso vai ser bastante complicado e vai ter que lidar com todos os tipos de casos especiais (sem número da residência, número da residência sem uma adição) ou questões internacionais (nos EUA, endereços são tipicamente como 1 Street).

Mas se você quiser a classificação como você descreveu e que é um requisito importante, que seria melhor para modelar você streetname em três partes, ou seja, rua (por exemplo, "Street"), numero_ porta (por exemplo, 1, 2, 12), house_num_addition ( por exemplo, "A", "B"). Em seguida, o tipo torna-se trivial em SQL.

Respondeu 09/12/2008 em 16:15
fonte usuário

votos
-1

Se for o caso de que todos os valores na coluna nomes de ruas seguem espaço o padrão StreetName- - StreetNumber

onde streetname pode conter outros espaços, mas StreetNumber não pode, então isso vai funcionar:

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))
Respondeu 09/12/2008 em 16:35
fonte usuário

votos
-1

Sim é possivel! Mas definitivamente não interessa! Se você encontrar alguém aqui pronto para passar algumas horas escrevendo e testando o SP que irá dividir seus nomes de ruas em uma combinação rua + streetNumber, dá-me o seu nome: Vou enviar-lhe alguns problemas onde eu pensei que eu tinha que pagar para obter o trabalho feito.

By the way, você não pode dividir seus dados em 2 campos, um 'da rua' apenas com o nome da rua, e um novo campo 'buildingNumber'? (Evite para citar este 'streetNumber', como, em alguns países / cidades, ruas são dadas números).

Respondeu 09/12/2008 em 16:13
fonte usuário

votos
-2

A maneira confiável para fazê-lo (confiável em termos de "para classificar seus dados corretamente", não "para resolver o seu problema geral") é dividir os dados em nome da rua e número e classificar os dois por conta própria. Mas isso exige saber onde o número da casa começa. E esta é a parte complicada - fazendo a suposição melhor se adapta seus dados.

Você deve usar algo como o seguinte refatorar seus dados e de agora em diante loja o número da casa em um campo separado. Tudo isso string de malabarismo não irá executar muito bem quando se trata de classificar grandes conjuntos de dados.

Assumindo que é a última coisa no nome da rua, e que contém um número:

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

Isto assume estas condições:

  • um endereço pode ter um número de casa
  • um número de casa deve ser a última coisa em um endereço (sem "525 Monroe Av.")
  • um número de casa deve começar com um dígito a ser classificados corretamente
  • um número de casa pode ser um intervalo ( "200-205"), este seria classificados abaixo de 200
  • um número de casa não deve conter espaços ou reconhecimento falhar (Quando você olha para os seus dados, você pode aplicar algo como REPLACE(street, ' - ', '-')higienizar padrões comuns de antemão.)
  • a coisa toda ainda é uma aproximação que, certamente, se desvia o que olharia como em um livro de telefone, por exemplo
Respondeu 09/12/2008 em 16:29
fonte usuário

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