2

多くの場合、データベースアイテムのリストと、各アイテムに関する特定の集計番号を表示する必要があります。たとえば、Stack Overflowでタイトルテキストを入力すると、[関連する質問]リストが表示されます。このリストには、関連するエントリのタイトルと、各タイトルの単一の集計された回答数が表示されます。

同様の問題がありますが、複数の集計が必要です。ユーザーオプションに応じて、3つの形式のいずれかでアイテムのリストを表示したい:

  • 私のアイテムの名前(合計15、私が所有する13)
  • 私のアイテムの名前(合計15)
  • 私のアイテムの名前(私が所有する13)

私のデータベースは次のとおりです。

  • アイテム:itemId、itemName、ownerId
  • カテゴリ:catId、catName
  • マップ:mapId、itemId、catId

以下のクエリは、カテゴリ名、カテゴリごとのアイテムIDの数を取得します。

SELECT
  categories.catName,
  COUNT(map.itemId) AS item_count
FROM categories
LEFT JOIN map
  ON categories.catId = map.catId
GROUP BY categories.catName

これは次のようになります:カテゴリ名、このowner_idのみのカテゴリごとのアイテムIDの数

SELECT categories.catName, 
COUNT(map.itemId) AS owner_item_count
FROM categories
LEFT JOIN map
  ON categories.catId = map.catId
LEFT JOIN items
  ON items.itemId = map.itemId
WHERE owner = @ownerId
GROUP BY categories.catId

しかし、1つのクエリで同時にそれらを取得するにはどうすればよいですか?つまり、カテゴリ名、カテゴリごとのアイテムIDの数、このowner_idのみのカテゴリごとのアイテムIDの数

ボーナス。オプションで、これらのいずれかについてcatId count!= 0のみを取得するにはどうすればよいですか?「WHEREitem_count<>0」を試してみると、次のようになります。

MySQL said: Documentation
#1054 - Unknown column 'rid_count' in 'where clause' 
4

3 に答える 3

5

ここにトリックがあります:SUM()1または0のいずれかであることがわかっている値のaを計算することは、値が1である行のaと同等COUNT()です。そして、ブール比較は1または0(またはNULL)を返すことがわかります。

SELECT c.catname, COUNT(m.catid) AS item_count,
  SUM(i.ownerid = @ownerid) AS owner_item_count
FROM categories c
  LEFT JOIN map m USING (catid)
  LEFT JOIN items i USING (itemid)
GROUP BY c.catid;

ボーナスの質問については、外部結合の代わりに内部結合を実行するだけで済みます。つまり、少なくとも1行mapが含まれるカテゴリのみが返されます。

SELECT c.catname, COUNT(m.catid) AS item_count,
  SUM(i.ownerid = @ownerid) AS owner_item_count
FROM categories c
  INNER JOIN map m USING (catid)
  INNER JOIN items i USING (itemid)
GROUP BY c.catid;

別の解決策がありますが、これはそれほど効率的ではありませんが、エラーが発生した理由を説明するために示します。

SELECT c.catname, COUNT(m.catid) AS item_count,
  SUM(i.ownerid = @ownerid) AS owner_item_count
FROM categories c
  LEFT JOIN map m USING (catid)
  LEFT JOIN items i USING (itemid)
GROUP BY c.catid
HAVING item_count > 0;

句の式は選択リストの式の前に評価されるWHEREため、句で列エイリアスを使用することはできません。WHEREつまり、選択リスト式に関連付けられた値はまだ使用できません。

、、、および句GROUP BYで列エイリアスを使用できます。これらの句は、選択リスト内のすべての式が評価された後に実行されます。HAVINGORDER BY

于 2008-11-11T19:27:04.733 に答える
4

SUM() 内に CASE ステートメントを忍び込ませることができます。

SELECT categories.catName, 
    COUNT(map.itemId) AS item_count,
    SUM(CASE WHEN owner= @ownerid THEN 1 ELSE 0 END) AS owner_item_count
FROM categories
LEFT JOIN map  ON categories.catId = map.catId
LEFT JOIN items  ON items.itemId = map.itemId
GROUP BY categories.catId
HAVING COUNT(map.itemId) > 0
于 2008-11-11T19:32:20.447 に答える
2
SELECT categories.catName, 
  COUNT(map.itemId) AS item_count,
  COUNT(items.itemId) AS owner_item_count
FROM categories
INNER JOIN map
  ON categories.catId = map.catId
LEFT JOIN items
  ON items.itemId = map.itemId
  AND items.owner = @ownerId
GROUP BY categories.catId

HAVINGon 句を使用できますowner_item_countが、内部結合が item_count を処理することに注意してください。

于 2008-11-11T19:48:35.157 に答える