0

いくつかの入力で結果を一覧表示できる SQL コマンドを作成しました。

そして、入力 ID 30 & 31 でこのように表示されます

    $sql ="SELECT ItemRelation.ItemRelTo, ItemRelation.Item, Items.CatID, Items.ItemID,   
    Items.Title, Items.Image, Items.Desc, Items.TimeStamp
    FROM Items
    INNER JOIN ItemRelation 
    ON ItemRelation.ItemRelTo=Items.ItemID
    WHERE ItemRelation.Item  In (30,31) 
    UNION
    SELECT ItemRelation.ItemRelTo, ItemRelation.Item, Items.CatID, Items.ItemID,     
    Items.Title, Items.Image, Items.Desc, Items.TimeStamp
    FROM Items
    INNER JOIN ItemRelation
    ON ItemRelation.Item=Items.ItemID
    WHERE ItemRelation.ItemRelTo In (30,31)";

そして、私のリレーションシップ テーブルは

Item    ItemRelTo
30      10
31      12
11      12
11      31
30      11

私のSQLの結果はItems.ItemID 10,11,11,12なので、アイテム11の重複が得られます.

そして、私が本当に欲しいのは、私の入力 (30,31) に共通するものであり、それは Items.ItemID = 11 であり、重複する値ではないため、結果は 1 つだけです。

そして、私はこれにかなり慣れていないので、ばかが理解できるように説明してください=)

結果を表示するコードの残りの部分は

$result = mysqli_query($con,$sql);
while($row = mysqli_fetch_array($result))
{
    echo '<tr>';
    echo '<td>' . $row['ItemID'] . '</td>';
    echo '<td>' . $row['Item'] . '</td>';
    echo '<td>' . $row['CatID'] . '</td>';
    echo '<td>' . $row['Title'] . '</td>';
    echo '<td><img src="Image/',$row['Image'],'"></td>';
    echo '<td>' . $row['Desc'] . '</td>';
    echo '<td>' . $row['TimeStamp'] . '</td>';
    echo '</tr>'; 
}

これが私の解決策になりました。おそらく、データベースが大きくなったときに Count を使用する最良の方法ではありません。そして、私がそこにたどり着くのを手伝ってくれたマイクに感謝します!

SELECT   Items.ItemID, GROUP_CONCAT(ItemRelation.ItemRelTo) AS ItemRelTo, Items.CatID,    
Items.Title, Items.Image, Items.Desc, Items.TimeStamp
FROM Items
INNER JOIN ItemRelation 
ON Items.ItemID = ItemRelation.Item
Where ItemRelTo IN (30,31)
Group By ItemID
HAVING COUNT(Items.ItemID) > 1
4

2 に答える 2

0

まず、UNION は使用しません。この SQL は次のように簡単に記述できます。

SELECT
  ItemRelation.ItemRelTo,
  ItemRelation.Item,
  Items.CatID,
  Items.ItemID,   
  Items.Title,
  Items.Image,
  Items.Desc,
  Items.TimeStamp
FROM Items
FULL JOIN ItemRelation
WHERE
  (
    Items.ItemID = ItemRelation.Item
    OR Items.ItemID = ItemRelation.ItemRelTo
  ) AND
  (
    ItemRelation.Item IN(30,31)
    OR ItemRelation.ItemRelTo IN(30,31)
  )

次に、DISTINCT id を表示するだけで、選択から ItemRelation データを削除して、次のように使用する必要がありますSELECT DISTINCT Items.ItemID

SELECT
  DISTINCT Items.ItemID,
  Items.CatID, 
  Items.Title,
  Items.Image,
  Items.Desc,
  Items.TimeStamp
FROM Items
FULL JOIN ItemRelation
WHERE
  (
    Items.ItemID = ItemRelation.Item
    OR Items.ItemID = ItemRelation.ItemRelTo
  ) AND
  (
    ItemRelation.Item IN(30,31)
    OR ItemRelation.ItemRelTo IN(30,31)
  )

または、GROUP BY Items.ItemID を使用することもできますが、その場合、ItemRelation データの異なる値をどのように表示するかを決定する必要があります。特定の集計なしで GROUP BY を実行すると、予測できない結果が生じるためです。デモンストレーションの目的で、GROUP_CONCAT の使用をお勧めします。

SELECT
  Items.ItemID,
  GROUP_CONCAT(ItemRelation.ItemRelTo) AS ItemsRelatedTo,
  GROUP_CONCAT(ItemRelation.Item) AS ItemRelations,
  Items.CatID, 
  Items.Title,
  Items.Image,
  Items.Desc,
  Items.TimeStamp
FROM Items
FULL JOIN ItemRelation
WHERE
  (
    Items.ItemID = ItemRelation.Item
    OR Items.ItemID = ItemRelation.ItemRelTo
  ) AND
  (
    ItemRelation.Item IN(30,31)
    OR ItemRelation.ItemRelTo IN(30,31)
  )
GROUP BY Items.ItemID

ここでの本当の問題はスキーマです。これらのリレーションが多対多で方向性がない場合 (このデータをクエリしようとしているように見えます)、次に行うべきことは、前方および後方リレーションの両方をリレーション テーブルに入れることです。関係を確立します。これにより、どちらの方向でもルックアップが可能になり、クエリで WHERE 句を重複させる必要がなくなります。

したがって、サンプルデータを更新すると、次のようになります。

Item    ItemRelTo
30      10
10      30
31      12
12      31
11      12
12      11
11      31
31      11
30      11
11      30

これにより、非常に単純化されたクエリを使用して、関係を持つアイテムを見つけることができます

SELECT
  Items.ItemID,
  GROUP_CONCAT(ItemRelation.ItemRelTo) AS ItemsRelatedTo,
  Items.CatID, 
  Items.Title,
  Items.Image,
  Items.Desc,
  Items.TimeStamp
FROM Items
INNER JOIN ItemRelation
  ON Items.ItemID = ItemRelation.Item
WHERE ItemRelation.ItemRelTo IN(30,31)
GROUP BY Items.ItemID
于 2013-07-30T22:19:17.587 に答える