0

私は次の問題を抱えています:

シナリオ:

問題を示し、無関係な詳細を非表示にするために、テーブル構造を再構成しました。

アイテムのテーブルがあるとしましょう。

Item: item_id | buyer_id | unit_id | status_id 

すべての列には、対応するテーブルを参照するnull以外の値があります。

私が持っている他のテーブルは、次の構造の価格カタログです。

Price: price_id | buyer_id | unit_id | status_id | price

ここで、参照値のいずれかは、「すべて」を意味する値「-1」を持つことができます。したがって、価格表に次の行を含めることができます。

| price_id | buyer_id | unit_id | status_id | price |
|        1 |       -1 |       1 |         2 |    15 |
|        2 |        1 |       1 |         2 |    25 |
|        3 |       -1 |      -1 |         3 |    13 |

ここで、価格1はアイテムを任意のbuyer_idおよびunit_id = 1status_id = 2と一致させ、価格2buyer_id = 1はアイテムをunit_id = 1およびで計算しますstatus_id = 2価格3buyer_idは、アイテムをany 、any unit_id、およびと一致させますstatus_id = 3

アイテムに一致する複数の価格がある場合、選択は次のロジックで行われます。指定されたフィールドが最も多い(-1の値の最小量)価格を取得します。-1の値が同じである複数の価格がある場合は、の-1とは異なる値を持つ価格を選択しますbuyer_id。そのようなものが存在しない場合はunit_id、ステータスで「not -1」の値を持つものを選択し、最後に「not-1」の値を持つものを選択します。

まったく同じ価格グループに一致する複数の価格はないと想定できます(すべての価格には、、、の一意の組み合わせがbuyer_idありunit_idますstatus_id)。

問題:

次に、item-table内の各アイテムに適切な価格を選択するクエリを作成する必要があります。これまでのところ私はこれを手に入れました:

SELECT item_id、price
FROMアイテム
    1=1の内部参加価格
        AND(price.buyer_id = item.buyer_id OR price.buyer_id = -1)
        AND(price.unit_id = item.unit_id OR price.unit_id = -1)
        AND(price.status_id = item.status_id OR price.status_id = -1)

基本的に、これはすべての一致する価格を取得します。したがって、が付いたアイテムがあり、buyer_id = 12つの行が得られる場合:unit_id = 1status_id = 2

| item_id | 価格|
| 1 | 15 |
| 1 | 25 |

私の最初のアイデアはを使用することGROUP BYでしたが、選択した価格が単なるランダム/最初の(?)価格ではなく、正しい価格になるようにそれを行う方法がわかりませんでした。

編集:行()を並べ替えてから、並べ替えられたサブクエリに基づいて結果をグループ化しようとしましORDER BY buyer_id DESC, unit_id DESC, status_id DESCたが、並べ替えはそのようには機能しないようです。

では、どうすれば正しい行を選択できますGROUP BYか?または、単一のクエリで適切な価格を取得するための代替ソリューションは何でしょうか(サブクエリで問題ありません)。

この特定のケースでは、テーブル構造を変更することは実際にはオプションではありません。

アップデート

以前に提出したソリューションを使用していますが、価格が選択される基準の量が3から5に増えました。これは、現在、CASE WHEN構造内に32の異なる組み合わせのリストがあることを意味します。別のものを追加する必要がある場合、リストは再び2倍になるので、私はまだより良い解決策を探しています。

4

1 に答える 1

0

今のところ、問題は次のように解決されました。それは仕事をし、少なくとも特定のケースでは十分に速く実行しますが、より良い解決策が存在することを願っています。今のところ、これがトリックです。

CASE可能な組み合わせのグループは非常に少ないので、さまざまな組み合わせの順序を表すために、各組み合わせに数値を与える句を作成するのは比較的簡単です。次に、item_idごとに、セレクター値が最小の行を選択します。これは、単純なグループ識別子、グループ内の最大値サブクエリで結合することによって行われます。アイデアを示すためのクエリは次のとおりです。

SELECT item_id, price
FROM (
    SELECT item_id, price,
        CASE
            WHEN price.buyer_id <> -1 AND price.unit_id <> -1 AND price.status_id <> -1 THEN 1
            WHEN price.buyer_id <> -1 AND price.unit_id <> -1 AND price.status_id =  -1 THEN 2
            WHEN price.buyer_id <> -1 AND price.unit_id =  -1 AND price.status_id <> -1 THEN 3
            WHEN price.buyer_id <> -1 AND price.unit_id =  -1 AND price.status_id =  -1 THEN 4
            WHEN price.buyer_id =  -1 AND price.unit_id <> -1 AND price.status_id <> -1 THEN 5
            WHEN price.buyer_id =  -1 AND price.unit_id <> -1 AND price.status_id =  -1 THEN 6
            WHEN price.buyer_id =  -1 AND price.unit_id =  -1 AND price.status_id <> -1 THEN 7
            WHEN price.buyer_id =  -1 AND price.unit_id =  -1 AND price.status_id =  -1 THEN 8
        END AS selector
    FROM item
        INNER JOIN price ON 1=1
            AND (price.buyer_id = item.buyer_id OR price.buyer_id = -1)
            AND (price.unit_id = item.unit_id OR price.unit_id = -1)
            AND (price.status_id = item.status_id OR price.status_id = -1) 
    ) AS all_possible_prices

    INNER JOIN (
    SELECT item_id, MIN(selector)
    FROM (
        SELECT item_id
            CASE
                WHEN price.buyer_id <> -1 AND price.unit_id <> -1 AND price.status_id <> -1 THEN 1
                WHEN price.buyer_id <> -1 AND price.unit_id <> -1 AND price.status_id =  -1 THEN 2
                WHEN price.buyer_id <> -1 AND price.unit_id =  -1 AND price.status_id <> -1 THEN 3
                WHEN price.buyer_id <> -1 AND price.unit_id =  -1 AND price.status_id =  -1 THEN 4
                WHEN price.buyer_id =  -1 AND price.unit_id <> -1 AND price.status_id <> -1 THEN 5
                WHEN price.buyer_id =  -1 AND price.unit_id <> -1 AND price.status_id =  -1 THEN 6
                WHEN price.buyer_id =  -1 AND price.unit_id =  -1 AND price.status_id <> -1 THEN 7
                WHEN price.buyer_id =  -1 AND price.unit_id =  -1 AND price.status_id =  -1 THEN 8
            END AS selector
        FROM item
            INNER JOIN price ON 1=1
                AND (price.buyer_id = item.buyer_id OR price.buyer_id = -1)
                AND (price.unit_id = item.unit_id OR price.unit_id = -1)
                AND (price.status_id = item.status_id OR price.status_id = -1) ) AS min_seeds
    GROUP BY item_id
    ) AS min_selectors ON all_possible_prices.item_id = min_selectors.item_id 
                            AND all_possible_prices.selector = min_selectors.selector
于 2013-03-20T20:25:40.167 に答える