假设我有以下表结构:
+--------------------------------------------+ +------------------------+ +--------------------+
| videos | | borrowings | | customers |
+-----+------------------------+-------------+ +----------+-------------+ +-----+--------+-----+
| id | title | genre | | video_id | customer_id | | id | name | sex |
+-----+------------------------+-------------+ +----------+-------------+ +-----+--------+-----+
| 101 | Transformers III | Action | | 101 | 101 | | 101 | Alfred | m |
+-----+------------------------+-------------+ +----------+-------------+ +-----+--------+-----+
| 102 | DNS - The Code of Life | Documentary | | 102 | 102 | | 102 | Agathe | f |
+-----+------------------------+-------------+ +----------+-------------+ +-----+--------+-----+
video_id -> videos.id
customer_id -> customers.id
我想选择按男女分类和分组的男性和女性借款数量。
+-------------+-------+---------+
| Genre | Males | Females |
+-------------+-------+---------+
| Action | 1 | 0 |
+-------------+-------+---------+
| Documentary | 0 | 1 |
+-------------+-------+---------+
我的第一次尝试只选择按流派分组的借款数
SELECT
v.genre "Genre",
COUNT(c.id) "Count"
FROM videos v
INNER JOIN borrowings b ON v.id = b.video_id
INNER JOIN customers c ON b.customer_id = c.id
GROUP BY v.genre
ORDER BY v.genre ASC;
我知道我可以在COUNT函数(或任何其他聚合函数)中执行SELECT,所以我的想法是做类似的事情(伪代码):
SELECT
v.genre "Genre",
COUNT(SELECT c.id FROM parent_selection_set WHERE c.sex = "m") "Borrowings from males",
...
但我怀疑有一个像parent_selection_set
这样的概念。 我想知道是否有办法在计数中使用SELECTs,或者是否有更好的方法来获得所需的结果?
答案 0 :(得分:2)
这就是您通常会得到您正在寻找
的结果的方法SELECT
v.genre "Genre",
COUNT(CASE WHEN c.sex = 'm' THEN 1 END) "Males",
COUNT(CASE WHEN c.sex = 'f' THEN 1 END) "Females"
FROM videos v
INNER JOIN borrowings b ON v.id = b.video_id
INNER JOIN customers c ON b.customer_id = c.id
GROUP BY v.genre
ORDER BY v.genre ASC;
您可以在Stack Overflow上找到很多问题,寻找如何创建PIVOT
tables in SQL。这个解决方案很快,因为在连接之后可以在内存中完成两个COUNT(...)
操作。
为了完整性'为了这个,您使用子查询寻找语法:
SELECT
v.genre "Genre",
(SELECT COUNT(*) FROM customers c WHERE b.customer_id = c.id AND c.sex = 'm') "Males",
(SELECT COUNT(*) FROM customers c WHERE b.customer_id = c.id AND c.sex = 'f') "Females",
FROM videos v
INNER JOIN borrowings b ON v.id = b.video_id
GROUP BY v.genre
ORDER BY v.genre ASC;
这些被称为correlated subqueries,它们比任何基于JOIN
的解决方案慢得多,因为通常,必须为顶级查询的每一行执行子查询。 / p>
答案 1 :(得分:1)
有多种可能性取决于RDBMS。 既然你没有使用RDBMS,这里有一个通用的SQL(通常适用于所有RDBMS,但有点长)
SELECT T.gr, T.cnt AS Total, TM.cnt AS Males, TF.cnt AS Females
FROM
(
SELECT v.genre AS gr, COUNT(c.id) AS cnt
FROM videos v
INNER JOIN borrowings b ON v.id = b.video_id
INNER JOIN customers c ON b.customer_id = c.id
GROUP BY v.genre
) T
LEFT JOIN
(
SELECT v.genre AS gr, COUNT(c.id) AS cnt
FROM videos v
INNER JOIN borrowings b ON v.id = b.video_id
INNER JOIN customers c ON b.customer_id = c.id
WHERE c.sex = 'm'
GROUP BY v.genre
) TM ON T.gr=TM.gr
LEFT JOIN
(
SELECT v.genre AS gr, COUNT(c.id) AS cnt
FROM videos v
INNER JOIN borrowings b ON v.id = b.video_id
INNER JOIN customers c ON b.customer_id = c.id
WHERE c.sex = 'f'
GROUP BY v.genre
) TF ON T.gr=TF.gr
ORDER BY T.gr ASC
在MySQL或Oracle中,您可以执行以下操作:
SELECT
v.genre "Genre",
COUNT(c.id) AS Tot,
COUNT(CASE WHEN (c.sex='m') THEN c.id ELSE 0 END) AS Males,
COUNT(CASE WHEN (c.sex='f') THEN c.id ELSE 0 END) AS Females
FROM videos v
INNER JOIN borrowings b ON v.id = b.video_id
INNER JOIN customers c ON b.customer_id = c.id
GROUP BY v.genre
ORDER BY v.genre ASC;
在Access或SQL Server中,您可以使用PIVOT语句