2012-04-21 66 views
0

基本上我有一张像这个例子的“歌曲”表。按字符串的一部分进行排序

enter image description here

我需要在一个gridview获取数据和显示。这张桌子很乱,歌曲可以按任​​何顺序播放,不一定按专辑或歌手分组。我需要先由歌手对行进行排序,然后按照字母顺序对艺术家进行排序。专辑也应该分组。但更重要的是,歌曲应按照字母顺序排列或按照编号排序。

上表显示了我想要的理想排序列表。任何人都可以指出如何为此编写T-SQL。我正在使用SQL Server 2008 R2。

+0

你想按照字母顺序还是按照编号排序歌曲吗?你不能这样做。 – 2012-04-21 17:22:24

+0

歌曲需要按照编号排序感谢:) – lawphotog 2012-04-22 18:46:33

回答

1

你需要选择是否要字母顺序在专辑中的歌曲(不太可能恕我直言)或数字(更容易,因为我不会除了最初的意图之外,不想以任何顺序听月亮的黑暗面。正如我在上面的评论中提到的那样,你不能同时做这两件事。

要按编号:

SELECT Title, Singer, Album 
    FROM dbo.Songs 
    ORDER BY Singer, Album, 
    CONVERT(INT, SUBSTRING(Title, 1, CHARINDEX('.', Title))); 

要按字母顺序排序标题:

SELECT Title, Singer, Album 
    FROM dbo.Songs 
    ORDER BY Singer, Album, 
    SUBSTRING(Title, CHARINDEX('.', Title) + 1, 255); 
    -- 255 or whatever the column is defined as 

很多人会建议LEN(Title)但对我来说,这是一个计算这是不必要的。唯一合理的情况是,恕我直言,是在架构快速发展并且该列的最大长度不能被认为是“稳定的”的情况下。在这些情况下,我可能仍然建议仅使用更高的数字,以适应该列未来的规模增长,例如4000

由于@ a1ex07暗示,您应该考虑分别存储号码和标题。你可以这样做如下:

ALTER TABLE dbo.Songs ADD SongNumber TINYINT; 
ALTER TABLE dbo.Songs ADD SongTitle VARCHAR(255); 

UPDATE dbo.Songs SET 
    SongNumber = CONVERT(TINYINT, SUBSTRING(Title, 1, CHARINDEX('.', Title))), 
    SongTitle = SUBSTRING(Title, CHARINDEX('.', Title) + 1, 255); 

-- once you've verified:  
ALTER TABLE dbo.Songs DROP COLUMN Title; 

你也必须更新访问该表的任何进程(或创建一个视图,并在观点它们)。现在,如果您想按SongNumberSongTitle排序,则您的ORDER BY条款要简单得多。 (但是你仍然无法按两种方式进行排序,如果你仔细想想它会很有意义。)

+0

+1很好的答案,除了微优化字符串操作。在2012年甚至提到'len'的代价是很古怪的。 – Andomar 2012-04-21 17:55:04

+0

@Andomar我不明白,为什么在不需要时进行计算,即使增量成本最小? – 2012-04-21 18:15:33

+0

让我清楚,我并不是建议使用LEN()的代码需要重写,就像在“我看到你有LEN()”那样,让我们​​通过删除它来提高查询性能“。这是微型优化,并没有保证。我的反对意见是,当一个尊敬的社区成员回答LEN()时,它不是必要的,浪费的,也不是原始问题的一部分。虽然是的“浪费”可以忽略不计,但我认为它背后的思想更具有毒性 - 整个“好吧,它并不昂贵......”有点像“磁盘空间便宜”的说法。 – 2012-04-21 18:26:20

1
select * 
from Songs 
order by 
     Singer 
,  Album 
,  Title 
+1

这将按数字排序,但不考虑OP的其他选项(按字母顺序排序标题 - 大概不包括前导'01.'等)。 – 2012-04-21 17:29:00

0

它看起来与由Singer, Album,Title排序的唯一问题是,标题中包含数字和字符串(因为它打破了1NF这是不好的)。如果你有绝对的把握title格式,你可以做

ORDER BY Singer, Album, 
cast(substring(Title,0,CHARINDEX('.',Title)) as int), 
substring(Title,CHARINDEX('.',Title)+1,LEN(Title)) 
-- LEN(Title) should work, even though it would be more correct to put the right number of 
-- characters (from position of '.' to the end) 
+0

我不认为'INT'会继续工作(也许你的意思是'VARCHAR(something)'?)。此外,我认为你的最后一个括号没有正确定位。 – 2012-04-21 17:23:58

+0

@ Aaron Bertrand:是的,复制时会出现误印。修复 – a1ex07 2012-04-21 19:13:36

+0

谢谢a1ex07,顺便说一句,你是什么意思它打破1NF?我承认我不是一个真正的前端设计师,也不是真正的数据库人员。你能为我建议一个更好的db界面吗?谢谢.. – lawphotog 2012-04-22 18:48:27