2012-07-18 48 views
2

我正在寻找一种方法,可以让我有一列,我只需手动输入一个数字,然后列表将自行排序基于此列表,这将使用c#作为语言的上市和它的MS SQL订购分数和混合数字列表

我没有太多的信息,但如果任何人想知道任何其他问题随时问,我会尽力回答我最好的能力。

它们当前存储为字符串。

导致它被扔出去的东西是因为一些列表包含范围,但一些包含分数,两者都显示相同的IE 1/2可能意味着1-2或1/2(一半)

所有的SQL连接都是使用NHibernate完成的。

不是简单地对它进行正常排序的原因是,列表目前使用分数排序,列表工作正常,但是当它超过1时,它似乎打破并抛出所有列表到列表的底部IE:我怎么会喜欢这个工作

Image List

例子:

我会在我的名为“DisplayOrder”或类似的规定数据库中的列。

数据库行表示“1”,这将是列表中的第一个项目出现。 数据库行显示“8”,这将是列表中的第8个项目出现。

+5

请提供样品数据和所需的输出。 – RedFilter 2012-07-18 14:14:26

+0

你只是想排序列表?你有什么理由要用数据库来做到这一点?这个列表中是否有重复项? – 2012-07-18 14:15:57

+0

我建议你在你的数据库查询顺序DisplayOrder asc – HatSoft 2012-07-18 14:16:40

回答

0

我已经把一个快速的函数来分析你的分数并将其转换为浮动,这可然后用于比较和分类。您可能需要更多的“卫生”步骤,可能使空白标准化,删除其他字符等,并且可能必须检查除数为零(只有您知道您的数据)。

create function dbo.FractionToFloat(@fraction varchar(100)) 
returns float 
as 
begin 
    declare @input varchar(100) 
     , @output float 
     , @whole int 
     , @dividend int 
     , @divisor int 

    -- Sanitize input 
    select @input = ltrim(rtrim(replace(replace(@fraction, '''', ''), '"', ''))) 

    select @whole = cast(case 
     when charindex('/', @input) = 0 then @input 
     when charindex(' ', @input) = 0 then '0' 
     else left(@input, charindex(' ', @input) - 1) 
     end as int) 

    select @dividend = cast(case 
     when charindex('/', @input) = 0 then '0' 
     when charindex(' ', @input) = 0 then left(@input, charindex('/', @input) - 1) 
     else substring(@input, charindex(' ', @input) + 1, charindex('/', @input) - charindex(' ', @input) - 1) 
     end as int) 

    select @divisor = cast(case 
     when charindex('/', @input) = 0 then '1' 
     else right(@input, charindex('/', reverse(@input)) - 1) 
     end as int) 

    select @output = cast(@whole as float) + (cast(@dividend as float)/cast(@divisor as float)) 

    return @output 
end 

这种方式,你可以简单地为了通过函数的输出就像这样:

select * 
from MyTable 
order by dbo.FractionToFloat(MyFractionColumn) 

通常我不会建议使用您自己的解析器,你必须保持作为数据的变化,但这种表面上似乎很简单,并且可能比手动维护序列列更好。另外,如果你必须比较不同的单位(英尺,英寸,分钟到秒),那么这变得更加复杂。我正在删除演示数据中看起来像单元的任何东西。

0

排序结果看起来非常正常,因为我真的认为数据库不明白“1 1/4”的含义。 哪种类型有你的数据库字段?文本/ varchar /字符串我猜?

也许你应该创建一个存储过程转换的分数值,数字的,一个则调用

SELECT field1, field2, ParseAndConvertProc(DisplayOrder) as disp_order ORDER by disp_order 
+0

我有一个默认的排序方法,在分钟时工作正常,直到它进入产品的范围,所以我们有一个产品这是1/2(一半),但他们也显示为一个范围是1/2(1-2),我认为最好的方式来解决这个问题将是简单地检查列是否为空,如果 – 2012-07-18 14:25:57

+0

这是行不通的,因为分数和范围的显示方式不同 – 2012-07-18 14:28:24

+0

是的,这是问题的一部分让我总结一下,看看我是否了解了一切:问题似乎是这样的:1)你的分数值被存储为文本(这使得它无法通过SQL-server解析为分数值,而没有明确的帮助/ proc)2)你的值没有固定的语法方案:有时'/' ,有时是' - ',有时候是'1 1/2'而不是'3/2',我错了吗? – mbarthelemy 2012-07-18 14:30:55

0

暂时忽略1/2可能意味着between 1 and 2,你可以处理疯狂,并尝试从中得到一些命令。

CREATE TABLE #Fractions (
    Frac varchar(15) 
); 

INSERT #Fractions VALUES 
    ('1 1/2'), ('1 1/4'), ('1"'), ('1/2'), ('1/4'), ('1/8'), 
    ('2 1/2'), ('2"'), ('3"'), ('3/4'), ('3/8'), ('4"'); 

WITH Canonical AS (
    SELECT 
     Frac, 
     F, 
     CharIndex(' ', F) S, 
     CharIndex('/', F) D 
    FROM 
     (SELECT Frac, Replace(Frac, '"', '') F FROM #Fractions) F 
    WHERE 
     F NOT LIKE '%[^0-9 /]%' 
), Parts AS (
    SELECT 
     Frac, 
     Convert(int, Left(F, CASE WHEN D = 0 THEN Len(F) ELSE S END)) W, 
     Convert(int, CASE WHEN D > 0 THEN Substring(F, S + 1, D - S - 1) ELSE '' END) N, 
     Convert(int, CASE WHEN D > 0 THEN Substring(F, D + 1, 2147483647) ELSE '1' END) D 
    FROM Canonical 
) 
SELECT 
    Frac, 
    W + N * 1.0/D Calc 
FROM Parts 
ORDER BY Calc; 

DROP TABLE #Fractions; 

但我不建议这样做。使用我的查询作为基础来获取正确的值,并切换到使用十进制值。

请注意,您还必须搜索您的数据以查找此代码未考虑的字符,使用上面的LIKE模式匹配代替NOT LIKE。然后删除它们或以某种方式解释它们。

如果你所说的是真的,1/2可能意味着两件事,你可以分辨它们之间的差异,那么你可以做一些事情。将范围存储在两列中。如果他们是相同的,那么就没有范围。

如果你不能区分这两种意义之间的区别,那么你只是大大搞砸了,不如放弃你的工作,去阿拉斯加参加比赛雪橇犬。