2

最初に整数order列にすべて NULL 値を含むテーブル T (以下の構造) があります。

col1 varchar(30),
col2 varchar(30)、
注文 int NULL

「colN」列を注文する方法もあります。

SELECT * FROM T ORDER BY some_expression_involving_col1_and_col2

順序値が上記の ORDER BY によって返される行の順序と一致するように、-IN SQL-数値順序値 1-N を順序テーブルに割り当てる最良の方法は何ですか?

言い換えれば、上記のクエリと 100% 同じ順序の行orderを返すように値を割り当てる単一のクエリ (Sybase SQL 構文のため、Oracle の行数はありません) が必要です。SELECT * FROM T ORDER BY order

クエリは必ずしもテーブル T をその場で更新する必要はありません。テーブル T2 のコピーを作成することでクエリが簡単になるのであれば問題ありません。

注 1: ソリューションは、ループやカーソルを含まない、実際のクエリまたは一連のクエリである必要があります。

注 2: データは上記の順序に従って一意に順序付け可能であると仮定します。2 つの行が同じ順序でランダムに割り当てられる状況について心配する必要はありません。

注3:私は一般的な解決策を好みますが、順序付け式の特定の例が必要な場合は、次のように言いましょう:

T から * を選択
ORDER BY CASE WHEN col1="" THEN "AAAAAA" ELSE col1 END, ISNULL(col2, "ZZZ")
4

3 に答える 3

4

例として、pubs2 の roysched テーブルを使用しました。列id(int NULL) を追加し、次の順序付けロジックとして使用しました。

substring(title_id,3,4) + right(replicate('0',5) + convert(varchar,lorange),5)

次に、ビューを作成 (および更新) しました。重複を避けるために、文字列を使用しました

Declare @strSql varchar(1000), @strOrder varchar(256)
set @strOrder = "substring(title_id,3,4) + right(replicate('0',5) + convert(varchar,lorange),5)"

set @strSql = "create view my_roysched (id,my_order)
as 
select id, (select count(*) from (select " + @strOrder + " as my_order from roysched) BETA 
              where BETA.my_order <= ALPHA.my_order) as my_id 
      from (select id," + @strOrder + " as my_order from roysched ) as ALPHA 

update my_roysched 
set id = my_order

drop view my_roysched"

exec (@strSql)

今あなたが与えるなら

select * from roysched
order by substring(title_id,3,4) + right(replicate('0',5) + convert(varchar,lorange),5)

id が上記の order by によって返された行の順序と一致することがわかります

于 2010-05-13T15:39:11.693 に答える
1

DVK

人々はあなたの特定の質問に答え、あなたは答えを選択しました。

しかし、この問題全体には、より深い問題があります。

  1. 私が理解できることから、これOrderはテーブルの列です。これは、行が表示される (または同様の) Order を識別します。あれは正しいですか ?

  2. その場合、テーブルは大幅に非正規化されています。3NF が壊れています (機能依存性ルールが壊れています)。列に派生値があります (重複した情報)。Update Anomalies が導入されました (列のデータを更新する場合、別の列の複製された [依存する] データを更新する必要があります)。

  3. それらの中で最も重要なのは、もちろん更新の異常です。(現在は非リレーショナルで正規化されていない) テーブルに行を挿入することはできなくなりました。Order挿入ごとに、テーブル内の少なくとも 1行、多くても 1 行おきに列を再計算して UPDATE する必要があります。

  4. そのどれも必要ありません。

    • 私はあなたの質問の範囲内でのみあなたの質問に答えることができ、Order列にデータを入力します(常にそれを維持するコードセグメントによって呼び出されます)。必要なコードは 5 行です。ベース テーブルに対する純粋な標準 SQL。ビューはありません。一時テーブルはありません。ループやカーソルはありません。OracleRANK()関数と同じように機能するため、汎用的です (テーブルと列の名前を置き換えるだけです)。

    • Orderしかし重要なのは、それがデータベース内の実際の列ではなく派生値である場合、実行時に列を生成するために使用できるコードと同じコードであるということです。この場合も、Order列と、それを維持するために必要なすべてのコードを削除できます。

    • したがって、Order 列に関係なく、ベース テーブルから直接 Order または Rank [派生] 値を生成するコードを提供することもできます。

  5. それに続いて、 の代入Orderは自明です。つまり、最初SELECTの を置き換えて、1 つのコード セグメントで両方の機能を実行します。COUNT()を別のコード セグメントとして使用する必要はありません。

興味ある ?

その場合、正確なcol_Nタイプと、値が何にOrder基づいているかを知る必要があります。最高の学生マーク. テーブル定義 (難読化) の方が簡単です。

コメントへの対応

  1. 一時テーブルの場合は、もっと簡単な方法、別のアプローチがあります。
    • Order列を与える
    • 次のように定義しますIDENTITY
    • SELECT入力に使用する に正しい があることを確認してくださいORDER BY
  2. Orderまだ計算が必要ですか?
    もしそうなら、すみません、この音をもっと素敵にする方法がわかりません。私 の質問に対する答えを知る必要はないと思われていることは承知しています。しかし、私が使用するコードはそのしきい値を超えています。そうでなければ、今までにコーディングしたことでしょう (SQL と Sybase の経験があるようです)。

    私は「下書き」ではなく、コードを 20 年間持っています。各インスタンスで、特定のテーブル名と列名をプラグインするだけで、10 秒かかります。したがって、私はコードが何を必要としているのかを知っています (つまり、コードが使用する論理原則を理解しています。コード自体は非常に単純です)。もちろんバリエーションもあります。これは単なる賢いコードではなく、論理的なソリューションだからです。他の誰かが 2 番目の列と一緒に 2 つの列を望んでいますDESCending

    • 問題を解決するよりも、問題を説明する方が常に時間がかかります。

    • 例えば。2つの列があります(説明は問題ありません、ありがとう)。しかし、(定義により) 1 つの列または集計のみを必要とする序数を求めています。の一意のクラスター化インデックスを想像してみてください。これは、特定する必要(col_1, col2)があると言っているものです。Orderなぜ関係があるのか​​ わかりませんcol_2。「KKKKKK」の行col_1の序数が 12345 の場合、「KKKKKL」の行の序数は 12346 である必要があります。col_2それらの2つの行のいずれかにあるものに関係なく。インデックスの先頭の列です。

    • 私が提供するコードは、その節で論理的に行っていることをすべてORDER BY考慮に入れる必要があります。そうしないと、「未完成」または「不完全」になり、いじる必要があります。その背後にある論理的原則を理解していないため、これはあなたにとって公平ではありません。

    • 次に、 の使用による複雑さがありますVARCHARs。これは簡単にコーディングできますが、それが何であるかを知る必要があります。クラスタ化インデックスの視覚化を使用して、次の 4 つのうちどれが正しいですか? 必要LTRIM()ですか? ( col_1 , col2)
      ( CONVERT( CHAR(30), col_1 ) , CONVERT( CHAR(30), col_2 ) )
      ( col_1 + col_2 ) -- as varchars
      ( CONVERT( CHAR(30), col_1 ) + CONVERT( CHAR(30), col_2 ) )

乾杯

于 2010-12-14T00:45:25.177 に答える
0

このソリューションが適切であることを願っています。

新しいフィールドをテーブル T に追加します (例: ID)

それで

T のセット ID = number() を更新します。Col1、Col2 による T オーダーから

使用している Sybase のバージョンは不明ですが、これは 5.5 で動作します。

select * from T order by col1, col2 は、select * from T order by ID と同じ結果になります。

乾杯AL

于 2010-12-10T04:41:44.547 に答える