1

ビルドするselectクエリがあり、正しく機能させることができません。私は、より高度なMySQL開発者からのいくつかの提案を期待していました。だから私のテーブルは:

 CREATE TABLE IF NOT EXISTS `gv` ( 
`id` int(11) NOT NULL AUTO_INCREMENT,
`option_id` int(11) NOT NULL,
`group_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ;

INSERT INTO `gv` (`id`, `option_id`, `group_id`) VALUES
(1, 1, 1),
(2, 2, 2),
(3, 3, 2),
(4, 4, 3),
(5, 5, 4),
(6, 6, 4); 

CREATE TABLE IF NOT EXISTS `igv` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `item_id` int(11) NOT NULL,
 `gv_id` int(11) NOT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=9 ;

INSERT INTO `igv` (`id`, `item_id`, `gv_id`) VALUES
(1, 1, 1),
(2, 1, 3),
(3, 2, 1),
(4, 2, 2),
(6, 3, 5),
(7, 4, 2),
(8, 2, 6); 

CREATE TABLE IF NOT EXISTS `items` (
  `item_id` int(11) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`item_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;

INSERT INTO `items` (`item_id`) VALUES
(1),
(2),
(3),
(4),
(5); 

次に、これらのテーブルが何をしているのかを説明します。

  1. gvはgroup_valuesから取得されます。グループは、アイテムのプロパティのようなものです。例:色。

    • 各行はグループの値を保持します。例:グループの色(group_id)の場合は赤(option_id)。
  2. igvは、アイテムグループの値から取得されます。アイテムは、製品のように、私のプロジェクトの主要なエンティティです。

    • 各行は、itemsとgroup_valuesの間の関係を保持します。例:赤い色のアイテム。
    • gv_id(igv.gv_id = gv.id)によってgvテーブルにリンクされています。
  3. itemsはitemsから来ています:)この例では、item_idという1つの列のみに簡略化しています。

クエリする必要があるもの:

さて、私のアプリでは、選択したアイテム(my_item)があります(0個以上のグループ値が添付されています)。まったく同じgroup_valuesが定義されているか、my_itemグループに値が指定されていないすべてのアイテムが必要です。PHPでは、アタッチされているすべてのグループをIDを持つ配列として抽出でき、すべてのgroup_valuesも抽出できます。しかし、このデータベースから必要なものを選択する方法が見つかりませんでした。この膨大な時間のかかる選択に提供されたあらゆる入力に感謝します。

ありがとう!

短いスケッチアップの例。左側には、すべての右側のアイテムに一致するアイテムがあります(コンマで区切られています)。 ここに画像の説明を入力してください

4

2 に答える 2

2

さて、最初に、別のアイテムと一致するグループを持つすべてのアイテムを見つける必要があります。

SELECT igv.item_id, sigv.item_id FROM igv
  INNER JOIN gv ON igv.gv_id = gv.id
  INNER JOIN gv sgv ON gv.group_id = sgv.group_id
  INNER JOIN igv sigv ON sigv.gv_id = sgv.id
  WHERE igv.item_id = items.item_id
    AND sigv.item_id = similar.item_id

次に、オプションが一致しない場合にのみ関心があります。

SELECT igv.item_id, sigv.item_id dissimilar FROM igv
  INNER JOIN gv ON igv.gv_id = gv.id
  INNER JOIN gv sgv ON gv.group_id = sgv.group_id
  INNER JOIN igv sigv ON sigv.gv_id = sgv.id
  WHERE igv.item_id = items.item_id
    AND sigv.item_id = similar.item_id
    AND gv.option_id != sgv.option_id

次に、上記で選択されていないアイテムのみに関心があります。NOT EXISTSこれは、またはのいずれかを使用して実行できますLEFT JOIN。これを行う方法は次のNOT EXISTSとおりです。

SELECT items.item_id, similar.item_id similar_id
  FROM items similar
  INNER JOIN items
  WHERE items.item_id != similar.item_id
    AND NOT EXISTS (
    SELECT igv.item_id, sigv.item_id dissimilar FROM igv
      INNER JOIN gv ON igv.gv_id = gv.id
      INNER JOIN gv sgv ON gv.group_id = sgv.group_id
      INNER JOIN igv sigv ON sigv.gv_id = sgv.id
      WHERE sigv.item_id = similar.item_id
        AND igv.item_id = items.item_id
        AND gv.option_id != sgv.option_id
    )

結果:

ITEM_ID SIMILAR_ID
1       3
1       5
2       4
2       5
3       1
3       4
3       5
4       2
4       3
4       5
5       1
5       2
5       3
5       4
于 2012-09-12T11:13:58.227 に答える
1

アップデート:

あなたのコメントからの論理、私がそれを正しく理解した場合、そしてあなたのテストデータに基づいて、次の表はあなたがクエリに提供するitem_idに対してどの結果が欲しいかを示しています。

id_provided | result
--------------------
1             2 & 5
2             1 & 4 & 5
3             5
4             2 & 5
5             -

これが正しければ、次のクエリで目的の結果が得られます。

SELECT 
COALESCE(i2.item_id, i.item_id)
FROM
items i
LEFT JOIN igv ON igv.item_id = i.item_id
LEFT JOIN gv ON igv.gv_id = gv.id
LEFT JOIN gv gv2 ON gv.group_id = gv2.group_id AND gv.option_id = gv2.option_id
LEFT JOIN igv igv2 ON gv2.id = igv2.gv_id
LEFT JOIN items i2 ON igv2.item_id = i2.item_id
WHERE i.item_id = $yourItemId
AND i2.item_id != i.item_id OR i2.item_id IS NULL



あなたが何を望んでいるかを理解したかどうかはわかりません。また、次のクエリがあなたが望むものを取得するかどうかもわかりません。期待される出力が何であるかを言わず、テストデータが十分でないためです。とにかく、これが私のショットです:

SELECT DISTINCT
i.item_id
FROM
items i
LEFT JOIN igv ON igv.item_id = i.item_id
LEFT JOIN gv ON igv.gv_id = gv.id
GROUP BY i.item_id
HAVING 
GROUP_CONCAT(CONCAT(COALESCE(gv.option_id, 0), COALESCE(gv.group_id, 0)) ORDER BY gv.option_id, gv.group_id SEPARATOR ':')
=
(
SELECT
GROUP_CONCAT(CONCAT(COALESCE(sq_gv.option_id, 0), COALESCE(sq_gv.group_id, 0)) ORDER BY sq_gv.option_id, sq_gv.group_id SEPARATOR ':')
FROM
items sq_i
LEFT JOIN igv sq_igv ON sq_igv.item_id = sq_i.item_id
LEFT JOIN gv sq_gv ON sq_igv.gv_id = sq_gv.id
WHERE sq_i.item_id = $yourItemId /*insert the item_id here*/
GROUP BY sq_i.item_id
)

于 2012-09-10T11:47:13.647 に答える