2

我正在寻找一种方法,可以让我有一个列,我只需手动输入一个数字,然后列表将根据该列表对自身进行排序,这将使用 c# 作为列表的语言,它是 ms SQL

我没有太多信息,但是如果有人想知道其他任何事情,请随时询问,我会尽力回答。

它们当前存储为字符串。

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

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

不简单地对其进行正常排序的原因是,列表目前使用分数排序并且列表工作正常,但是当它超过 1 时,它似乎会中断并将它们全部扔到列表 IE 的底部:

图像列表

我希望它如何工作的示例:

我会在我的数据库中有一个名为“DisplayOrder”的列或类似的东西。

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

4

3 回答 3

0

排序结果似乎完全正常,因为我真的认为数据库不理解“1 1/4”的含义。哪种类型有你的数据库字段?我猜是文本/varchar/字符串?

也许您应该创建一个存储过程来将小数值转换为数字,然后调用

SELECT field1, field2, ParseAndConvertProc(DisplayOrder) as disp_order ORDER by disp_order
于 2012-07-18T14:19:48.370 回答
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)

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

于 2012-07-18T18:25:00.637 回答
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可能意味着两件事,并且你能分辨出它们之间的区别,那么你可以做点什么。将范围存储在两列中。如果它们相同,则没有范围。

如果您无法区分这两种含义之间的区别,那么您只是一团糟,还不如辞掉工作去阿拉斯加赛雪橇犬。

于 2012-07-18T21:06:12.547 回答