0

次のような製品、カテゴリ、および「productsInCategories」のデータベースがあります。


ユーザー

id█  name  ▌
▀▀█▀▀▀▀▀▀▀▀▌
1 █  john  ▌
69█  jane  ▌

製品

id█  name  █ cost █description▌
▀▀█▀▀▀▀▀▀▀▀█▀▀▀▀▀▀█▀▀▀▀▀▀▀▀▀▀▀▌
21█snickers█  23  █ foo       ▌
34█  mars  █  20  █ bar       ▌
37█  daim  █  21  █ oofrab    ▌
79█ banana █  8   █ foobar    ▌
80█  apple █  10  █ barfoo    ▌

カテゴリー

id█  userId █   name  ▌
▀▀█▀▀▀▀▀▀▀▀▀█▀▀▀▀▀▀▀▀▀▌
10█    69   █chocolate▌
55█    69   █favorites▌
20█    1    █ fruit   ▌

カテゴリー内の製品

categoryId█productId▌
▀▀▀▀▀▀▀▀▀▀█▀▀▀▀▀▀▀▀▀▌
    10    █   21    ▌
    10    █   34    ▌
    20    █   79    ▌
    20    █   80    ▌
    55    █   21    ▌
    55    █   37    ▌

これにより、次のように見なすことができるものが生成されます。

Users
   john
      fruit
         banana
         apple
   jane
      chocolate
         snickers
         mars
         daim
      favorites
         snickers
         daim

カテゴリのすべての製品を取得したいときは、次のようにします。

SELECT *
FROM Products
        INNER JOIN ProductsInCategories
        ON Products.Id=ProductsInCategories.product
        WHERE category=@0
,@0=categoryId

それはすべて正常に機能しており、製品の挿入または削除は非常に簡単です. しかし、私は今、頭を包むことができない問題を抱えています。

つまり、カテゴリを削除します。どうすればそれを行うことができますか?私は何時間もそれに取り組んできましたが、うまくいかないようです。ユーザーがカテゴリを削除すると、そのカテゴリにのみ存在するすべての製品が、関連する productInCategories-records と共に削除されます。ユーザー「ジェーン」が彼女のカテゴリ「チョコレート」を削除すると、「お気に入り」カテゴリにも存在するため、「スニッカーズ」や「マーズ」ではなく、製品「マーズ」を削除したいとします。

4

2 に答える 2

5

スキーマでカスケード削除を設定しない限り、テーブルごとに 1 つずつ、合計 3 つの削除ステートメントを使用する必要があります。

-- Delete category 10 from Categories table.
DELETE FROM Categories WHERE Id=10;

-- Delete category 10 from ProductsInCategories table.
DELETE FROM ProductsInCategories WHERE CategoryId=10;

-- Delete all products that are no longer in a category    
DELETE Products
FROM Products
LEFT JOIN ProductsInCategories
  ON ProductId=Products.Id
WHERE ProductId IS NULL;

でテストする SQLfiddle

于 2013-05-12T09:02:54.240 に答える
1

あなたを動かすためのいくつかの疑似コード:

 Delete from ProductsIncategories where category = X

 Delete from products where productID in (
    select productID from
        products left outer join productsincategories 
        on products.productID = productsincategories.productID
    where 
        productsincategories.categoryid is null
 )

 delete from categories where category = x
  1. 最初にカテゴリ内の製品を削除すると、そのまま他のテーブルに依存し、それに依存するものは何もありません。

  2. 現在、カテゴリのない製品を探します - これらは、削除するカテゴリにのみ含まれていたものです - これは、製品から製品カテゴリへの左外部結合によって行われます - これにより、製品のすべての行が返され、製品の一致するレコードがない場合は null が返されますカテゴリで

  3. 何もリンクされていないため、カテゴリ自体を削除します。

補足として、このカテゴリの製品のみを削除するのではなく、レビューとクリーンアップのためにこれらのレポートを提供することを検討してください. そうしないと、作業が頻繁に失われる可能性があるようです。たぶん、少なくとも削除する前に確認する機会を彼らに与えてください

また、中間のステートメントは、カテゴリに含まれていないすべての製品を削除することに注意してください..このような問題については、2 つの考え方があります。

  1. カテゴリにない製品は間違いなので、できる限りすべてをクリーンアップしてください
  2. 製品にカテゴリがない理由はいろいろありますが、これは私には役に立ちません!

このカテゴリにのみ含まれていた製品のみを削除したいが、一括削除がうまくいかない場合は、次のような方法が役立ちます。

select productID form
from
    products as p
    inner join productsincategories as pic
        on PIC.productid = p.productid
    inner join (
        select distinct productID from productsincategories 
        where categoryid = X
    ) as t
        on t.productid = p.productid
 group by 
    productid
 having 
    count(*) = 1

ここでは、Joachim Isaksson のフィドルを使用した select の動作を示します (今すぐ Joachim の回答に +1 を付けます)

http://sqlfiddle.com/#!3/5a744/22

LEFT OUTER JOINS - クイック ノート

table a
id
1
2


table b
aID   value
1     x
1     y


a left outer join b (select * from a left outer join b on a.id = b.aID)
id  aID value
1   1   x
1   1   y
2   NULLNULL

b left outer join a (select * from b left outer join a on a.id = b.aID)
aID value id
1   x     1
1   y     1

左外部結合は、左側のテーブルからすべてを取得し、右側のテーブルから一致します。左側のテーブルに行があり、右側にない場合、右側のテーブルのすべての列に対して NULL が返されます。それが役立つことを願っていますが、慣れるためにグーグルと実験の価値があります.

すべての商品の売上を調べたいが、売上の有無にかかわらず商品リストを取得したい場合に非常に便利です。または、ここで使用したように、「正しい」テーブルがnullの場所を選択するだけで、あるテーブルにあり、別のテーブルにないすべてを見つけることができます

于 2013-05-12T08:53:52.847 に答える