DAY01 SQL训练


前言

提示:这里可以添加本文要记录的大概内容:

最近,在训练牛客题库SQL必知必会,这里写练习笔记作为积累。

每日一题,2023年10月29日,上午。


提示:以下是本篇文章正文内容,下面案例可供参考

一、分析思路

Step1:题意明确:

了解复旦大学每个用户8月份练习的总题目数和回答正确的题目数情况,请取出相应明细数据,对于在8月份没有练习过的用户,答题数结果返回0.

Step2:问题分解:

1)限制条件:用户信息表、答题详细表

2)日期:使用month函数

3)总的题目数:count函数

4)正确题目数:sum函数

5)where过滤

6)分类聚合:group by

Step3:细节问题:

1)细节1:

`month(qpd.date) = 8` 是一个SQL查询中的条件表达式,它用于从日期数据中提取月份并检查是否等于8。让我详细解释它的含义和相关的知识点:

1. **`month(qpd.date)`**:这部分使用了一个日期函数 `month()`,它的作用是从给定日期中提取月份部分。这个函数通常接受一个日期或日期时间作为参数,并返回一个表示月份的整数值。

2. **`= 8`**:这是一个比较操作,用于检查提取的月份是否等于8。

所以,`month(qpd.date) = 8` 的含义是:如果从日期 `qpd.date` 中提取的月份部分等于8,那么这个条件将评估为真,否则为假。

相关的知识点包括:

- **SQL日期函数**:SQL提供了一系列日期和时间函数,用于处理日期和时间数据。其中,`month()` 是一个常见的函数,用于提取日期中的月份部分。其他日期函数还包括 `day()`(提取天)、`year()`(提取年份)等。

- **比较操作符**:`= 8` 是一个比较操作符,用于比较两个值是否相等。在这种情况下,它比较提取的月份是否等于8。

- **条件表达式**:`month(qpd.date) = 8` 是一个条件表达式,通常用于筛选数据,以便仅包括满足特定条件的记录。

- **日期和时间处理**:在SQL中,日期和时间数据的处理非常常见,因为它们在许多应用中都起着关键作用。在查询中,您通常会使用日期函数和条件来对日期数据进行操作和筛选。

2)细节2:

`count()` 和 `sum()` 是 SQL 中用于聚合数据的函数,但它们用于不同的目的,因此有一些重要的区别:

1. **count() 函数**:
   - `count()` 用于计算某个列中非 NULL 值的行数。
   - 它通常用于计算特定列中的记录数。例如,`count(question_id)` 计算 'question_id' 列中非 NULL 值的行数,因此它表示问题的总数量。
   - 结果总是一个整数值,表示计数。

2. **sum() 函数**:
   - `sum()` 用于计算某个列中数值的总和。
   - 它通常用于计算数值列的总和。在这种情况下,`sum(if(qpd.result='right', 1, 0))` 计算 'question_practice_detail' 表中 'result' 列值等于'right'的行的数量,因为它将满足条件的行(1)加在一起,得到总数。
   - 结果是一个数值,可能是整数或小数,取决于列中的数据类型。

总结区别:
- `count()` 用于计算行数或特定列中非 NULL 值的行数,返回整数。
- `sum()` 用于计算数值列中的总和,返回数值。通常,它还可以用于计算特定条件下的行数,通过将条件映射为数值并对其进行求和。

3)细节3:

这两种写法的区别在于放置连接条件的位置以及其对结果集的影响。比较并解释这两种写法的区别与联系:

**代码1**:

```sql
select up.device_id, '复旦大学' as university,
    count(question_id) as question_cnt,
    sum(if(qpd.result='right', 1, 0)) as right_question_cnt
from user_profile as up
left join question_practice_detail as qpd
  on qpd.device_id = up.device_id 
where up.university = '复旦大学' and month(qpd.date) = 8
group by up.device_id
```

**代码2**:

```sql
select up.device_id, '复旦大学' as university,
    count(question_id) as question_cnt,
    sum(if(qpd.result='right', 1, 0)) as right_question_cnt
from user_profile as up
left join question_practice_detail as qpd
  on qpd.device_id = up.device_id  and month(qpd.date) = 8
where up.university = '复旦大学'
group by up.device_id
```

**区别**:

- **代码1** 将 `month(qpd.date) = 8` 放在 `WHERE` 子句中,这意味着在连接 `user_profile` 和 `question_practice_detail` 表之前,先筛选出月份为8的记录。这将导致只有符合月份条件的记录将被关联,且可能导致某些 `user_profile` 表中的用户信息在结果中缺失。
- **代码2** 将 `month(qpd.date) = 8` 放在 `ON` 子句中,这意味着在连接 `user_profile` 和 `question_practice_detail` 表时,已经包括了月份条件。这将确保所有 `user_profile` 表中的用户信息都包括在结果中,即使他们在月份为8之外没有问题练习记录。

**联系**:

- 共同之处是两个查询的结果集都包括了属于'复旦大学'的用户,并且都计算了问题总数(question_cnt)和正确问题总数(right_question_cnt)。
- 两种写法都使用了 `LEFT JOIN` 来关联 `user_profile` 和 `question_practice_detail` 表,以保留 `user_profile` 表中所有用户的信息。

**选择哪种写法** 取决于您的需求。如果您希望仅包括在特定月份内有问题练习记录的用户信息,那么使用代码1的方式是合适的。如果您希望包括所有用户信息,并且只筛选问题练习记录的月份为8,那么使用代码2的方式是更合适的。

二、完整代码

select up.device_id, '复旦大学' as university,
    count(question_id) as question_cnt,
    sum(if(qpd.result='right', 1, 0)) as right_question_cnt
from user_profile as up
left join question_practice_detail as qpd
  on qpd.device_id = up.device_id  and month(qpd.date) = 8
where up.university = '复旦大学'
group by up.device_id


总结

提示:这里对文章进行总结:

Step5:复盘。

在上述SQL查询中,使用 `GROUP BY` 语句的目的是对查询的结果进行分组。

这是因为查询的目标是获取每个复旦大学的用户在8月份练习的总题目数和回答正确的题目数情况。而数据库中的数据通常以行的形式存储,每行代表一个用户的练习记录。因此,使用 `GROUP BY` 是为了对结果进行适当的聚合和分组,以获得每个用户的综合统计数据。

为什么使用 `GROUP BY` 的原因:

1. **聚合操作**:使用 `COUNT` 和 `SUM` 函数进行聚合操作,这些函数会对数据进行汇总,而不是每个记录单独计算。通过 `GROUP BY`,您可以指定按哪个列进行分组,这将决定每个分组内的汇总结果。

2. **避免重复计算**:如果没有使用 `GROUP BY`,查询将返回每个用户的每一条练习记录,这会导致数据的重复和混乱。使用 `GROUP BY` 可以确保每个用户只出现一次,并且在结果集中表示为一个单独的行。

3. **更好的可读性**:聚合查询结果通常更容易理解和解释。通过使用 `GROUP BY`,您可以轻松地查看每个用户的练习统计数据,而不必处理重复的记录。

总之,使用 `GROUP BY` 是为了将数据按用户分组,以便进行聚合操作,并以更有意义和可读性的方式呈现用户的统计信息。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值