3

MySQL5.0.88で製品検索を正しく機能させようとしています。

基本設定:製品を含むテーブルAがあります

A.id
A.ean
A.styleNo
A.price
A.seller (ID e.g. 123, 456)

そして価格表のある表B

B.name
B.ean
B.alt_price
B.seller

売り手は、検索を行うユーザーに一致するオプションの価格表を定義できます。私の検索は多かれ少なかれ次のようになります:

    SELECT A.styleNo, A.price, B.price
    FROM arts A
        LEFT JOIN pricelists B ON
                B.seller = A.seller 
            AND B.ean = A.ean 
            AND B.alt_price != 0
    WHERE...
    // pricelists
    AND ( B.name = "some_name" AND B.seller = "123" ) OR ( next applicable seller ) ...

したがって、LEFT JOINの後に、価格表のすべてのアイテムを名前と販売者別に含めます。

これは、通常価格(A)とalt_price(B)の両方を選択し、結果を表示するときに既存のalt_priceをチェックして、ユーザーに正しい価格を表示できるため、問題なく機能します。

ただし、売り手がすべての商品に代替価格を指定していない場合、実際には価格表がないこの売り手の商品を表示したくないのに、Aの価格で商品を表示しています。エントリー(地域の品揃えを考えてください)。

したがって、ユーザーXに価格表「abc」があり、売り手123に500個の製品があり、そのうち200個が価格表「abc」にある場合、正しい価格で500個の200個ではなく、200個の製品のみを表示します。

LEFT JOINでB.alt_price!= 0を使用しようとしましたが、そこにあるすべてのアイテムに価格があるため、これは役に立ちません。

質問
実際の検索でこれを行う方法はありますか、それとも結果ループで行う必要がありますか。これはあまり熱心ではありません。

4

3 に答える 3

2
SELECT 
    b.styleNo, b.price, a.alt_price
FROM
    pricelists a
INNER JOIN
    arts b ON a.seller = b.seller AND a.ean = b.ean
WHERE
    a.alt_price <> 0 AND
    a.name = 'name' AND
    a.seller = 123

ここで行っているのは、フィールドが両方のテーブルで一致INNER JOINする場合にのみ行を返すことです。したがって、でフィルタリングされた価格表にある商品のみが取得されます。sellereanWHERE

一方、 ALEFT JOINは、他のテーブルに一致するものがあるかどうかに関係なく、すべての行を返します。一致する場合は2番目のテーブルの対応する値が表示されますが、一致しない場合はNULL、最初のテーブルの行データを保持したまま、2番目のテーブルの値になります。

したがって、代わりに実行した場合FROM arts a LEFT JOIN pricelists b ON ...、価格表テーブルに一致するものがあるかどうかに関係なく、productsテーブルからすべての行を取得します。価格表が一致しなかった場合でも、商品は表示されますが、NULL値を含む価格表データが表示されます。

の左側のテーブルでは、右側LEFT JOINテーブルの一致に関係なく、行データが保持されていることに注意してください...したがって「LEFT」。LEFT JOIN

さまざまなタイプがどのように機能するかを理解するために、 JeffAtwoodによる結合の視覚的な説明を確認することをお勧めしますJOIN

また、これは結合後WHEREに評価されるため、で指定した条件付きフィルタリングは、結合が行われた後に適用されることを理解してください。したがって、table2の行がのtable1の行と一致しない場合にのみすべての行が必要な場合は、を指定します。WHERELEFT JOINWHERE table2.fieldname IS NULL

于 2012-07-15T20:30:47.877 に答える
0

外部結合ではなく内部結合が必要なようです。内部結合は、結合条件が成功した組み合わせのみを返します。左結合は、左テーブルの各行に対して常に少なくとも1つの行を返します。

代替価格の製品のみを入手するには、次のようにします。

SELECT A.styleNo, A.price, B.price
    FROM arts A
        INNER JOIN pricelists B ON
                B.seller = A.seller 
            AND B.ean = A.ean 
            AND B.alt_price is not null
    WHERE...

または、現在のクエリのwhere句に追加AND B.alt_price is not nullすることもできますが、dbのクエリオプティマイザが引き継がない限り、効率が低下する可能性があります。

于 2012-07-15T19:26:20.350 に答える
0

Ok。ついに解決策を見つけました。

問題は、検索に複数の売り手が含まれることです。価格表を使用する人と使用しない人がいます。

  • 価格表Bで内部結合を行うと、Bにエントリがないため、価格表を使用しない販売者の製品を取得できません。
  • 価格表BでLEFTJOINを実行すると、すべてのエントリの値がNULLまたは価格表Bになるため、一部の商品に価格表を使用している販売者を検索すると、alt_priceに関係なく、常に全範囲が取得されます。指定
  • WHERE句にB.alt_price!= 0を追加して、これらの不要なレコードをフィルタリングしようとすると(売り手は価格表を使用し、価格表にない商品を除外します)、価格表を使用していない売り手からすべての商品を除外します。

私はそれを次のように解決しました:-とにかくこの行を作成する必要があります:

LEFT JOIN pricelists B ON
       // dynamic construct depending on number of sellers using pricelists matched to user
            B.seller = A.seller 
        AND B.ean = A.ean 
        AND B.alt_price != 0
  • そこで、価格表を使用し、このユーザーに適用できるすべての販売者IDを含む別の変数を作成しました。このように見えます:

    123,456,789..。

  • これをWHERE句に追加します。

    AND(IF(A.seller IN(123,456,789 ...)、B.alt_price IS NOT NULL、1))

このようにして、
(a)レコードがユーザーに該当する価格表の販売者からのものであるかどうかを確認し、
(b)その場合、レコードのb.alt_priceにNULL値が含まれていてはなりません。 LEFT JOININGの場合、sqlは価格表BにないすべてのレコードにNULLを追加するため、価格表にあります。

それは難しかった...

于 2012-07-15T19:37:41.520 に答える