0

シリーズとカードの 2 つのテーブルがあります (1 対多: 各シリーズには多くのカードがあります)。

series: seriesID, seriesName...
cards: cardID, seriesID, cardActive (bit), cardUsed(bit)

次のクエリを返したい:

  • 各シリーズには合計何枚のカードがありますか?
  • 各シリーズには何枚の非アクティブ カードがありますか?
  • 各シリーズの使用済みカードは何枚ですか?
  • 各シリーズには、未使用およびアクティブなカードが何枚ありますか?

目標は、次のヘッダーを持つテーブルを持つことです。

seriesID | seriesName | total cards count | inactive cards | etc..

私はこれを使ってみました:

SELECT seriesID,COUNT(*) AS cardsCount FROM cards GROUP BY seriesID

しかし、指定された統計を取得するために 5 つの異なるクエリが必要かどうか疑問に思っています。関数を使用する必要がありますか?

4

1 に答える 1

1

おそらくビットフィールドを合計することができます (それが INTEGER ではなくパリティ値を生成しない限り)。CASE 式は最後に役立ちます。

 SELECT s.SeriesID,
        s.SeriesName,
        COUNT(*)              AS "Total Cards",
        SUM(NOT c.CardActive) AS "Inactive Cards",
        SUM(NOT c.CardUsed)   AS "Unused Cards",
        SUM(CASE WHEN c.CardActive AND NOT c.CardUsed THEN 1 ELSE 0 END)
                              AS "Active and Unused"
   FROM Series AS s
   JOIN Cards  AS c ON s.SeriesID = c.SeriesID
  GROUP BY s.SeriesID, s.SeriesName;

それが MySQL であることを考えるとs.SeriesName、GROUP BY を省略でき、おそらく同じ答えになるでしょう。他のほとんどの DBMS は、GROUP BY 句で両方の非集計列を要求します。

SUM(NOT c.CardActive)and式が意図したとおりに動作しない可能性がありSUMN(NOT c.CardUsed)ます。その場合:

       SUM(CASE WHEN c.CardActive THEN 0 ELSE 1 END) AS "Inactive Cards",
       SUM(CASE WHEN c.CardUsed   THEN 0 ELSE 1 END) AS "Unused Cards",

トリックを行います。

これは、少なくとも 1 枚のカードがリストされているシリーズではすべて問題ありません。カードがないシリーズがあり、それらを出力に含める場合は、テーブル間に LEFT OUTER JOIN が必要であり、null について心配する必要があります。今回SUM(CASE...END)は全体で が必要になります。COUNT(C.CardID)null 以外の値のみをカウントするため、シリーズにカードがない場合はゼロになることに注意してください。

 SELECT s.SeriesID,
        s.SeriesName,
        COUNT(c.CardID) AS "Total Cards",
        SUM(CASE WHEN c.CardID IS NULL THEN 0 WHEN c.CardActive THEN 0 ELSE 1 END)
                        AS "Inactive Cards",
        SUM(CASE WHEN c.CardID IS NULL THEN 0 WHEN c.CardUsed   THEN 0 ELSE 1 END)
                        AS "Unused Cards",
        SUM(CASE WHEN c.CardID IS NULL THEN 0
                 WHEN c.CardActive AND NOT c.CardUsed THEN 1 ELSE 0
            END)        AS "Active and Unused"
   FROM Series AS s
   LEFT JOIN Cards AS c ON s.SeriesID = c.SeriesID
  GROUP BY s.SeriesID, s.SeriesName;
于 2012-06-04T02:37:22.850 に答える