0

我有两张桌子,系列和卡片(一对多:每个系列都有很多卡片)

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

您可能可以对位字段求和(除非产生奇偶校验值而不是整数),并且 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)andSUMN(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",

会成功的。

对于至少列出一张卡的系列来说,这一切都是干净的。如果您有没有卡片的系列并且您希望它们在输出中,那么您需要在表之间使用 LEFT OUTER JOIN,并且您必须担心空值。这一次,SUM(CASE...END)整个过程都需要。请注意,COUNT(C.CardID)仅计算非空值,因此当系列没有卡片时这将为零。

 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 回答