web-dev-qa-db-ja.com

SQLのリンクリスト

リンクリストをmysqlデータベースに保存する最良の方法は、挿入が簡単になるように(つまり、毎回大量のインデックスを再作成する必要がない)、リストを簡単に順番に取り出すことができるようにすることです。

57

'position'と呼ばれるテーブルに整数列を保存します。リストの最初のアイテムに0、2番目のアイテムに1などを記録します。データベースのその列にインデックスを付け、値を引き出したい場合はその列でソートします。

 alter table linked_list add column position integer not null default 0;
 alter table linked_list add index position_index (position);
 select * from linked_list order by position;

インデックス3に値を挿入するには、行3以上の位置を変更してから、次を挿入します。

 update linked_list set position = position + 1 where position >= 3;
 insert into linked_list (my_value, position) values ("new value", 3); 
16
Adrian Dunston

Adrianのソリューションを使用しますが、1ずつインクリメントする代わりに、10または100ずつインクリメントします。挿入は、挿入の下のすべてを更新することなく、挿入するものの差の半分で計算できます。挿入の平均回数を処理するのに十分な大きさの数字を選択します。小さすぎる場合は、挿入中に高い位置にあるすべての行を更新する必要があります。

17
cfeduke

previousIDとNextIDの2つの自己参照列を持つテーブルを作成します。アイテムがリストの最初のものである場合、PreviousIDはnullになり、最後のアイテムである場合、NextIDはnullになります。 SQLは次のようになります。

create table tblDummy
{
     PKColumn     int     not null, 
     PreviousID     int     null, 
     DataColumn1     varchar(50)     not null, 
     DataColumn2     varchar(50)     not null,  
     DataColumn3     varchar(50)     not null, 
     DataColumn4     varchar(50)     not null, 
     DataColumn5     varchar(50)     not null, 
     DataColumn6     varchar(50)     not null, 
     DataColumn7     varchar(50)     not null, 
     NextID     int     null
}
15
B0fh

リンクリストは、テーブル内の再帰ポインターを使用して保存できます。これは、SQLに保存されている階層とほぼ同じであり、再帰的な関連付けパターンを使用しています。

詳細については、こちらをご覧ください こちら

これがお役に立てば幸いです。

4
user9252

最も簡単なオプションは、リストアイテムごとの行、アイテムの位置の列、およびアイテム内の他のデータの列を持つテーブルを作成することです。次に、position列でORDER BYを使用して、目的の順序で取得できます。

create table linked_list
(   list_id   integer not null
,   position  integer not null 
,   data      varchar(100) not null
);
alter table linked_list add primary key ( list_id, position );

リストを操作するには、位置を更新し、必要に応じてレコードを挿入/削除します。インデックス3のリスト1にアイテムを挿入するには:

begin transaction;

update linked_list set position = position + 1 where position >= 3 and list_id = 1;

insert into linked_list (list_id, position, data)
values (1, 3, "some data");

commit;

リストの操作には複数のコマンドが必要になる場合があるため(たとえば、挿入にはINSERTおよびUPDATEが必要です)、必ずトランザクション内でコマンドを実行してください。

この単純なオプションのバリエーションは、100などの各アイテムに対して何らかの要因で位置をインクリメントすることです。これにより、INSERTを実行するときに、次の要素の位置の番号を常に変更する必要がなくなります。ただし、次の要素をインクリメントするタイミングを決めるには少し手間がかかるため、多くの挿入がある場合は単純さは失われますが、パフォーマンスが向上します。

要件に応じて、次のような他のオプションが魅力的です。

  • リストに対して多くの操作を実行し、取得回数を少なくしたい場合は、位置列を使用する代わりに、リスト内の次のアイテムを指すID列を使用することをお勧めします。次に、アイテムを順番に取得するために、リストの取得で反復ロジックを実行する必要があります。これは、ストアドプロシージャに比較的簡単に実装できます。

  • リストが多数あり、リストをテキスト/バイナリにシリアル化および逆シリアル化する簡単な方法で、リスト全体を保存および取得したい場合、リスト全体を単一の値として単一の列に保存します。おそらくあなたがここで求めているものではないでしょう。

4
Rory

https://dba.stackexchange.com/questions/46238/linked-list-in-sql-and-trees は、高速挿入と順序付けのために浮動小数点位置列を使用するトリックを示唆しています。

また、特殊なSQL Server 2014 hierarchyid 機能についても言及しています。

2
Vadzim

これは私がしばらく自分で理解しようとしてきたことです。私がこれまでに見つけた最良の方法は、次の形式(これは擬似コードです)を使用してリンクリスト用の単一のテーブルを作成することです。

LinkedList(

  • key1、
  • 情報、
  • key2

key1は開始点です。 Key2は、次の列でそれ自体にリンクする外部キーです。したがって、あなたの列は何かをリンクします

col1

  • key1 = 0、
  • information = 'hello'
  • key2 = 1

Key1はcol1の主キーです。 key2は、col2のkey1につながる外部キーです

col2

  • key1 = 1
  • information = 'wassup'
  • key2 = null

col2のkey2は、何も指し示していないため、nullに設定されます

テーブルに最初に列を入力するとき、key2がnullに設定されていることを確認する必要があります。そうしないと、エラーが発生します。 2番目の列を入力したら、戻って最初の列のkey2を2番目の列の主キーに設定できます。

これにより、一度に多くのエントリを入力してから、それに応じて外部キーを設定する(またはそれを行うGUIを構築する)最良の方法が作成されます。

私が用意した実際のコードをいくつか示します(実際のコードはすべてMSSQLで機能しました。使用しているSQLのバージョンについて調査することをお勧めします!)。

createtable.sql

create table linkedlist00 (

key1 int primary key not null identity(1,1),

info varchar(10),

key2 int

)

register_foreign_key.sql

alter table dbo.linkedlist00

add foreign key (key2) references dbo.linkedlist00(key1)

* 2つのステップで行う必要があるため、2つの別々のファイルに入れました。 MSSQLでは、外部キーを参照するためのテーブルがまだ存在しないため、1ステップで実行することはできません。

リンクリストは、1対多の関係で特に強力です。では、外部キーの配列を作成したいと思ったことはありませんか?さて、これはそれを行う1つの方法です!リンクリストテーブルの最初の列を指すプライマリテーブルを作成し、「情報」フィールドの代わりに、目的の情報テーブルへの外部キーを使用できます。

例:

フォームを保持する官僚制があるとしましょう。

file cabinetというテーブルがあるとしましょう

ファイルキャビネット(

  • キャビネットID(pk)
  • ファイルID(fk))

各列には、キャビネットの主キーとファイルの外部キーが含まれています。これらのファイルは、納税申告書、健康保険証書、フィールドトリップ許可証などです

ファイル(

  • ファイルID(pk)

  • ファイルID(fk)

  • 次のファイルID(fk)

これはファイルのコンテナとして機能します

ファイル(

  • ファイルID(pk)

  • ファイルに関する情報

これは特定のファイルです

あなたの特定のニーズに応じて、これを行うより良い方法があるかもしれません。この例は、可能な使用法を示しています。

2
HumbleWebDev

この投稿は古いですが、それでも私の.02 $を提供します。テーブルまたはレコードセットのすべてのレコードを更新することは、順序付けを解決するのが面倒です。インデックス作成の量もおかしくなりますが、ほとんどの人が受け入れているようです。

更新とインデックス作成を減らすために思いついたクレイジーなソリューションは、2つのテーブルを作成することです(ほとんどの場合、すべてのレコードを1つのテーブルに並べ替えます)。ソートされるリストのレコードを保持するテーブルAと、順序のレコードを文字列としてグループ化して保持するテーブルB。順序文字列は、WebサーバーまたはWebページアプリケーションのブラウザレイヤーで選択されたレコードを順序付けるために使用できる配列を表します。

Create Table A{
Id int primary key identity(1,1),
Data varchar(10) not null
B_Id int
}

Create Table B{
Id int primary key Identity(1,1),
GroupName varchat(10) not null,
Order varchar(max) null
}

注文文字列の形式は、id、位置、および文字列をsplit()するための区切り文字である必要があります。 jQuery UIの場合、.sortable( 'serialize')関数は、リスト内の各レコードのIDと位置を含むPOST friendlyである注文文字列を出力します。

本当の魔法は、保存された順序付け文字列を使用して、選択したリストを並べ替える方法です。これは、構築しているアプリケーションによって異なります。アイテムのリストを並べ替えるjQueryの例を次に示します。 http://ovisdevelopment.com/oramincite/?p=155

2
FlyTigert

SERIAL 'index'を100増やしますが、Prev + Next/2に等しい 'index'を持つ中間値を手動で追加します。100行を飽和させた場合は、インデックスを100に並べ替えます。

これにより、プライマリインデックスの順序が維持されます。

1
Stephen

私はすぐに考えることができるいくつかのアプローチがあり、それぞれ異なるレベルの複雑さと柔軟性があります。実際のリンクリストとしてストレージを必要とするのではなく、取得の順序を保持することがあなたの目標であると考えています。

最も簡単な方法は、テーブル内の各レコードに順序値を割り当てることです(1、2、3、...など)。次に、レコードを取得するときに、順序列で順序を指定して、順序どおりに戻します。

このアプローチでは、リストのメンバーシップに関係なくレコードを取得できますが、1つのリストのメンバーシップのみが許可され、レコードが属するリストを示すために追加の「リストID」列が必要になる場合があります。

もう少し複雑ですが、より柔軟なアプローチは、リストにメンバーシップに関する情報を保存することです。テーブルには3つの列が必要です。リストID、序数値、およびデータレコードへの外部キーポインターです。このアプローチでは、基礎となるデータはリストのメンバーシップについて何も知らず、複数のリストに簡単に含めることができます。

1
Mike Monette

Datetimeタイプの作成された列とintの位置列を追加する方がずっと簡単だと思うので、selectステートメントでorder by位置、descオプションを作成し、リストを順番に取得します。

1
Poncho

列にオフセット(リストインデックスの位置)を含めることで、リストを保存できます。中央に挿入すると、新しい親より上にすべてが追加され、挿入が行われます。

0
Daniel Papasian