简体   繁体   English

如何在MySQL上构建SQL查询以检索GROUP BY统计信息

[英]How to build an SQL query on MySQL that retrieves GROUP BY statistics

I have two tables, series and cards (one to many: each series has many cards) 我有两个表,系列和卡(一对多:每个系列有很多卡)

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

I want to return a query of: 我想返回一个查询:

  • how many total cards does each series have? 每个系列有多少张总牌?
  • how many inactive cards does each series have? 每个系列有多少个闲置卡?
  • how many used cards does each series have? 每个系列有多少张二手卡?
  • how many unused and active cards does each series have? 每个系列有多少个未使用和活动的卡?

The goal is to have a table with the following headers: 目标是创建一个带有以下标题的表:

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

I've tried using this: 我试过使用这个:

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

but I wonder whether I would need 5 different queries to get the specified statistics. 但我想知道是否需要5个不同的查询才能获得指定的统计信息。 Should I use a function? 我应该使用功能吗?

You can probably SUM the bit-fields (unless that produces a parity value rather than an INTEGER), and the CASE expression helps with the last: 您可能可以对位字段求和(除非产生奇偶校验值而不是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;

Given that it is MySQL, you could omit s.SeriesName from the GROUP BY and you'd probably end up with the same answer; 鉴于它是MySQL,您可以从GROUP BY中省略s.SeriesName ,您可能最终会得到相同的答案。 most other DBMS would demand both non-aggregate columns in the GROUP BY clause. 其他大多数DBMS都需要GROUP BY子句中的两个非聚合列。

There's a chance that the SUM(NOT c.CardActive) and SUMN(NOT c.CardUsed) expressions won't do what I want. SUM(NOT c.CardActive)SUMN(NOT c.CardUsed)表达式可能无法满足我的要求。 In that case: 在这种情况下:

       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",

will do the trick. 会成功的

This is all clean for the series which have at least one card listed. 对于列出至少一张卡的系列来说,这是干净的。 If you have series where there are no cards and you want them in the output, then you need a LEFT OUTER JOIN between the tables, and you have to worry about nulls. 如果您有没有卡的系列并且想要在输出中使用它们,那么您需要在表之间有一个LEFT OUTER JOIN,并且您必须担心null。 This time, the SUM(CASE...END) is going to be needed throughout. 这次,将始终需要SUM(CASE...END) Note that COUNT(C.CardID) only counts the non-null values, so this will give zero when the series has no cards. 请注意, 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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM