2

手動で数字を入力するだけの列を持つことができる方法を探しています。リストはこのリストに基づいてソートされます。これは、リストの言語として c# を使用し、ms SQL です。

あまり情報がありませんが、他に何か知りたいことがあれば、お気軽にお尋ねください。できる限りお答えします。

それらは現在、文字列として保存されています。

それが投げ出される原因は、一部のリストには範囲が含まれているが、一部には分数が含まれているためです。どちらも同じように表示されます IE 1/2 は 1-2 または 1/2(半分) を意味します

すべての SQL 接続は、NHibernate を使用して行われます。

単純に通常どおりに並べ替えない理由は、現在、リストが分数を使用して並べ替えられており、リストが正常に機能しているためです。ただし、1 を超えると、壊れてすべてがリスト IE の一番下にスローされるようです。

画像一覧

これをどのように機能させたいかの例:

データベースに「DisplayOrder」という名前の列、またはそれらの行に沿ったものがあります。

データベース行は「1」と表示されます。これは、リストの最初に表示される項目になります。データベースの行に「8」と表示されている場合、これはリストの 8 番目に表示される項目になります。

4

3 に答える 3

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 1/4」の意味を理解していないと思うので、ソート結果は完全に正常に見えます。あなたのデータベースフィールドはどのタイプですか? Text/varchar/string だと思いますか?

小数の値を数値に変換するストアド プロシージャを作成し、 then を呼び出す必要があるかもしれません。

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

しかし、これはお勧めしません。私のクエリをベースとして使用して正しい値を取得し、10 進数値の使用に切り替えます。

NOT LIKE の代わりに LIKE を使用して上記のパターン マッチを使用して、このコードで説明されていない文字をデータから検索する必要があることにも注意してください。次に、それらを削除するか、何らかの方法で説明します。

あなたの言ったことが真実であり、それ1/2が 2 つのことを意味し、それらの違いを見分けることができれば、それについて何かをすることができます。範囲を 2 列に格納します。それらが同じ場合、範囲はありません。

この 2 つの意味の違いがわからない場合は、単に頭がおかしくなっているだけで、仕事を辞めてアラスカで犬ぞりのレースに出かけたほうがよいでしょう。

于 2012-07-18T21:06:12.547 に答える