我想列出(排序列表)我的表/关系Customers中名为streetNames的属性的所有条目。 例如。我想达到以下顺序:
Street_1A
Street_1B
Street_2A
Street_2B
Street_12A
Street_12B
streetNames的一个简单的顺序将进行词汇比较,然后Street_12A和B将在Street_2A / B之前出现,这是不正确的。是否有可能通过纯SQL来解决这个问题?
答案 0 :(得分:2)
从tablex中选择street_name 按udf_getStreetNumber(street_name)
排序 你的udf_getStreetNumber中的- 编写业务规则以删除号码
修改
我认为您现在可以在SQL Server中使用正则表达式功能。我只是从输入中删除所有非数字字符。
答案 1 :(得分:2)
记录:它被称为自然排序顺序,并且有一个Coding horror article 在这个主题。
我猜你可以在SQL中使用这里显示的一些代码来完成它,但它总是在一个案例场景中。
答案 2 :(得分:1)
我确信你可以将streetName字段分成不同的部分,例如substr(streetName,1,find(“”,streetName)),仅用于街道等等。但这将是相当混乱的,它将不得不处理各种特殊情况(没有门牌号码,门牌号码没有增加)或国际问题(在美国,地址通常像1街道)。
但是如果你想按照你所描述的那样排序并且这是一个重要的要求,那么最好将streetName建模为三个部分,即街道(例如“街道”),house_number(例如1,2,12) ,house_num_addition(例如“A”,“B”)。然后在SQL中排序变得微不足道。
答案 3 :(得分:1)
如果您对数据库具有写访问权限,我建议将其全部转换为使用3个单独的字段,然后适当地使用它们。这样你甚至可以在PHP中使用它(是的,它需要一些时间,但它只会发生一次)。 如果你有一个庞大的代码库,必须检查这个表的所有查询,这可能会有些痛苦,但最终会得到回报。例如,它将使地址搜索更容易。
答案 4 :(得分:-1)
是的,这是可能的!但绝对没有兴趣!如果你发现有人在这里准备花几个小时写下并测试将你的streetNames拆分为streetName + streetNumber组合的SP,请给我他的名字:我会向他提出一些我认为必须支付的问题已完成的工作。
顺便说一下,你不能将你的数据分成2个字段,一个只有街道名称的'streetName'和一个新的'buildingNumber'字段? (避免将此名称命名为'streetNumber',因为在某些国家/城市,街道上有数字)。
答案 5 :(得分:-1)
如果是streetNames列中的所有值都遵循该模式 StreetName- space - StreetNumber
其中StreetName可以包含其他空格,但StreetNumber不能包含,那么这将起作用:
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))
答案 6 :(得分:-2)
可行的方法(在“正确排序数据”方面可靠,而不是“解决您的一般问题”)是将数据拆分为街道名称和门牌号码,并自行对它们进行排序。但这需要知道门牌号码的起始位置。这是棘手的部分 - 使假设最适合您的数据。
您应该使用以下内容来重构您的数据,并从现在开始将门牌号存储在一个单独的字段中。在排序大型数据集时,所有这些字符串杂乱都不会表现得太好。
假设它是街道名称中的最后一个,它包含一个数字:
DECLARE @test TABLE
(
street VARCHAR(100)
)
INSERT INTO @test (street) VALUES('Street')
INSERT INTO @test (street) VALUES('Street 1A')
INSERT INTO @test (street) VALUES('Street1 12B')
INSERT INTO @test (street) VALUES('Street 22A')
INSERT INTO @test (street) VALUES('Street1 200B-8a')
INSERT INTO @test (street) VALUES('')
INSERT 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
这假定了这些条件:
REPLACE(street, ' - ', '-')
之类的内容来清理常见模式。)