0

データベース構造の設計上の問題があります。目標は、クライアントが特定の地域ごとに提供するオファーのデータベースを作成することです。各オファーは、多くの地域で提供できます。

地域は階層化されています - 例:

subregion_1
  subregion_11
    region_111
    region_112
  subregion_12
    region_121
    region_122
subregion_2
  subregion_21
    region_221

今、offer_1 とそのオファーの地域をデータベースに保存したいと考えています。私が達成しなければならないことの例を 3 つ挙げます。

  • offer_1 が region_111 に格納されている場合、ユーザーが subregion_1、subregion_11、および region_111 を閲覧しているときにこのオファーを表示したいと考えています。
  • offer_1 が領域 subregion_11 および region_121 に格納されている場合、ユーザーが subregion_1、subregion_11、および subregion_11、subregion_12、および region_121 のすべてのブランチを閲覧しているときにオファーが表示されます。
  • 私の offer_1 が subregion_1 に格納されている場合、オファーは subregion_1 ページに表示され、subregion_1 の下のすべてのブランチが表示されます。

また、各地域のさまざまなオファーの数を動的かつ非常に高速に計算する方法を提供する必要があります。このデザインにアプローチする方法について誰かアドバイスがありますか?

これが私がこれまでに持っているものです。

Regions
------------------------------------------------------------
| id     | level1 | level2 | level3 | name         | level |
------------------------------------------------------------
| 02     | 02     | null   | null   | subregion_1  | 1     |
| 0201   | 02     | 01     | null   | subregion_11 | 2     |
| 020103 | 02     | 01     | 03     | region_111   | 3     |
------------------------------------------------------------

Offers to regions
------------------------
| offer_id | region_id |
------------------------
| 1        | 020103    |
| 1        | 0202      |
------------------------

level1、level2、および level3 を連結して、リージョンの ID を作成しました。テーブル Offers_to_regions に、オファーと地域を保存します。ここでは、オファー 1 に対してレベル 3 (020103) のリージョンとレベル 2 (0202) のリージョンがあります。この設計では、リージョンごとの異なるオファーの数を照会する方法と、レベル 1、レベル 2 のリージョンのオファーを照会する方法に問題があります。およびレベル 3 リージョン。

4

1 に答える 1

1

さて、このような親を指すためにidを使用する明白な方法があります

CREATE TABLE Regions (
    region_id INT AUTO_INCREMENT PRIMARY KEY,
    parent_id INT,
    region_name VARCHAR(100) NOT NULL,
    FOREIGN KEY (parent_id) REFERENCES Regions(region_id)
);

しかし、あなたの状況では、階層を介してクエリを実行するのはそれほど簡単ではないため、これはアンチパターンと見なすことができます(特にレベルの数が変更された場合)

別のアプローチは、たとえばUNIXパスに似た階層パスを格納するPathEnumerationのようなものを使用することです。例えば

CREATE TABLE Regions (
    region_id INT AUTO_INCREMENT PRIMARY KEY,
    path VARCHAR(100),
    region_name VARCHAR(100) NOT NULL
);

これにより、このように階層を保存できます

---------------------------------------------
| region_id | path       | region_name      |
---------------------------------------------
| 1         | 1/         | subregion_1      |
| 2         | 1/2/       | subregion_11     |
| 3         | 1/2/3/     | region_111       |
| 4         | 1/2/4/     | region_112       |
---------------------------------------------

このように、オファーテーブル(各オファーにはregion_idへの参照があります)をクエリするとき、およびブラウジング中にsubregion_1(id 1)のオファーを言うと、クエリは次のようになります。

select Offers.SOME_COLUMN, ......
from Offers, Regions
where Offers.region_id = Regions.region_id
and   Regions.path like '1/%'

階層データをモデル化する他のパターンがあります。たとえば、ネストされたセットクロージャーテーブル関連する可能性があります)など、同様に調べることができます。選択/挿入/削除のパフォーマンスに関して、それぞれに長所と短所があります

編集:

質問を編集したことに気づきました。また、オファーは複数の地域に属している可能性があります。上記は、複数のリージョンの割り当てをサポートするために調整が必要な場合がありますが、基本的な考え方は引き続き適用できます。

于 2011-12-02T21:28:55.827 に答える