0

いくつかのテーブルからデータを選択していますが、主な考え方は、製品には、割引率またはドル割引額として関連付けられた割引レコードがある場合とない場合があるということです。左外部結合 (間違っている可能性があります) を使用していますが、レコードが存在するかどうかに関係なく、ドルとパーセントの値に同じ値が返されます。

クエリは次のようになります。

SELECT Items.ItemID, Items.name, Items.price, 
       ItemDiscounts.percentOff, ItemDiscounts.dollarOff, 
       ItemAttributes.ColorName, ItemStuff.StuffID
FROM Items, ItemAttributes, ItemStuff
LEFT OUTER JOIN ItemDiscounts
  ON ItemDiscounts.ItemID = ItemID
  AND (
    ItemDiscounts.percentOff > 0
    OR ItemDiscounts.dollarOff > 0
  )
WHERE Items.ItemID = ItemAttributes.ItemID
AND ItemStuff.ItemID = Items.ItemID
GROUP BY ItemStuff.StuffID

奇妙な部分は、各アイテムに独自の割引レコードが関連付けられているかどうかに関係なく、すべての結果でpercentOff「1」を返し、「0」を返すことです。dollarOff唾の場合は、 に変更ItemDiscounts.percentOff > 0してからItemDiscounts.percentOff > 1dollarAmountすべて 2に変更し、percentOffすべて 0 でした。

私はこれにやや困惑しているので、助けていただければ幸いです。

4

3 に答える 3

1

ON 句に ItemID への非修飾参照があります...「あいまいな列」例外がスローされない理由が明確ではありません。(どうやら、MySQL にはあいまいではなく、MySQL はどの ItemId が参照されているかを判断しています。意図したものではない可能性が高いです。

また、クエリには行ソースへの参照が含まれていますがItemStuff、そのような行ソースはクエリに表示されていません。

また、 の動作がGROUP BY期待に沿わない結果セットを提供していると思われます。(おそらく、現時点では、意図しない操作であるクエリの実際の問題が隠されてCROSS JOINいます。

句なしでクエリを試してGROUP BY、結果セットが GROUP BY 句がない場合に期待するものであることを確認することをお勧めします。

注: 他のほとんどのリレーショナル データベース エンジンはGROUP BY、クエリに表示されるような例外をスローします。それらは (基本的に) SELECT リスト内のすべての非集計が に含まれていることを要求しますGROUP BY。MySQL を同じように動作させることができます (sql_mode のいくつかの特定の設定を使用)。

注: 存在しない行ソースへの参照が与えられた場合、このクエリがどのようにセマンティクス チェックに合格し、結果セットを返すのかItemStuffわかりません。


読みやすくするために、結合演算子としてカンマを使用せず、代わりに JOIN キーワードを使用することをお勧めします。また、結合述語をWHERE句から句に移動することもお勧めしますON。また、各行ソースに別名を付け、その別名を使用して列を修飾することも好みます。

クエリで表示される内容を考えると、次のように記述します (理解できる部分)。

SELECT i.ItemID
     , i.name
     , i.price
     , d.percentOff
     , d.dollarOff
     , a.ColorName
  FROM Items i 
  JOIN ItemAttributes a
    ON a.ItemID = i.ItemID
  LEFT 
  JOIN ItemDiscounts d
    ON d.ItemID = i.ItemID
       AND ( d.percentOff > 0 OR d.dollarOff > 0 )

ItemStuff.StuffID行ソースが表示されないため、SELECT リストから除外しItemStuffました。

クエリに行ソースが表示されないため、WHERE 句も除外しItemStuffます。

-- WHERE ItemStuff.ItemID = i.ItemID

GROUP BY を省略します。これも、クエリに ItemStuff 行ソースが表示されないためです。また、GROUP BY の動作は期待したものではなく、クエリの問題を隠している可能性が高いためです。

-- GROUP BY ItemStuff.StuffID

アップデート:

@Kyle、クエリが「タイムアウト」したという事実により、デカルト積があるように、予想よりもはるかに多くの行を生成していると思います(テーブルのすべての行が他のテーブルのすべての行に「一致」しています。 .. 1 つのテーブルに 10,000 行、もう 1 つのテーブルに 10,000 行、100,000,000 行が生成されます。

GROUP BYこの条項は本当の問題を覆い隠していると思います。

開発のために、各テーブルの PRIMARY KEY を結果セットの先頭の列として含めることをお勧めします。駆動テーブルに合理的な述語をいくつか追加します (たとえばi.ItemID IN (2,3,5,7)、結果セットのサイズを制限し、主キーで ORDER BY を実行します...これは、意図しないデカルト積を識別するのに役立ちます。

于 2012-07-24T18:48:39.353 に答える
0

クエリからこれらの行を削除すると、必要なものが得られますか?

AND (アイテムディスカウント.パーセントオフ > 0 OR アイテムディスカウント.ドルオフ > 0)

于 2012-07-24T18:37:03.917 に答える
0

外部結合の null の可能性がある側に絶対値を指定すると、WHERE句でそれを考慮する必要があります。

次の句で試してください。

AND (
ItemDiscounts.percentOff > 0
OR ItemDiscounts.percentOff is null
OR ItemDiscounts.dollarOff > 0
OR ItemDiscounts.dollarOff is null
)

さらに、GROUP BY集計なしで を指定しています。これはほとんどの場合意味がありません。あなたはおそらくORDER BYソートしたいでしょう。

于 2012-07-24T18:46:07.853 に答える