赞
踩
Person
表中所有重复的电子邮箱。select Email from Person group by Email having count(Email)>1;
Customers
表和 Orders
表。编写一个 SQL 查询,找出所有从不订购任何东西的客户。select c.name Customers from Customers c where c.id not in(select CustomerId from Orders);
select name from customer where ifnull(referee_id,0)!=2;
表:SalesPerson(销售人员的姓名和 ID ,以及他们的工资、佣金率和雇佣日期。)
Company(公司的名称和 ID ,以及公司所在的城市。)
Orders(这包括公司的 ID 、销售人员的 ID 、订单日期和支付的金额。)
编写一个SQL查询,报告没有任何与名为 “RED” 的公司相关的订单的所有销售人员的姓名。
请你编写一个 SQL 查询来交换所有的 'f' 和 'm' (即,将所有 'f' 变为 'm' ,反之亦然),仅使用 单个 update 语句 ,且不产生中间临时表。
用case....when....then....else...end
1)update salary set sex= case sex when 'm' then 'f' else 'm' end;
用if
2)update salary set sex = if(sex = 'm', 'f', 'm');
用ascii
3)update salary set sex = char(ascii(sex) ^ ascii('m') ^ ascii('f'));
解析:每一个字母都对应一个 ascii ,使用 ascii() 就可以把字母转换成 ascii ,在利用异或,相同的数为 0, 0 和任何数进行异或都是那个数,再利用 char 将 ascii 码转换成字母
具体的步骤:
ascii('m') 为 109 , ascii('f') 为 102
ascii('m') ^ ascii('m') ^ ascii('f') ,所以转化成 109 ^ 109 ^ 102 , 109 和 109 异或为 0 , 0 和 102 异或为 102 ,在用 char(102) 得出结果为 m 。
ascii('f') ^ ascii('m') ^ ascii('f') ,所以转化成 102 ^ 109 ^ 102 ,可以交换下 109 和 102 的位置,所以 102 和 102 异或为 0 , 0 和 109 异或为 109 ,在用 char(109) 得出结果为 f 。
编写一个SQL查询,报告2019年春季
才售出的产品。即仅在2019-01-01
至2019-03-31
(含)之间出售的商品。(注意有些商品可能在2019年春季
售出,在其他时间也在售出,这种商品应该排除)
select p.product_id,p.product_name from product p join sales s on p.product_id=s.product_id group by p.product_id having min(sale_date)>='2019-01-01' and max(sale_date)<='2019-03-31';
select activity_date day,count(distinct user_id) active_users from activity where datediff('2019-07-27',activity_date)>=0 and datediff('2019-07-27',activity_date)<30 group by activity_date;
部门表 Department
:
+---------------+---------+ | Column Name | Type | +---------------+---------+ | id | int | | revenue | int | | month | varchar | +---------------+---------+ (id, month) 是表的联合主键。 这个表格有关于每个部门每月收入的信息。 月份(month)可以取下列值 ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]。
编写一个 SQL 查询来重新格式化表,使得新的表中有一个部门 id 列和一些对应 每个月 的收入(revenue)列。查询结果格式如下面的示例所示:
Department 表: +------+---------+-------+ | id | revenue | month | +------+---------+-------+ | 1 | 8000 | Jan | | 2 | 9000 | Jan | | 3 | 10000 | Feb | | 1 | 7000 | Feb | | 1 | 6000 | Mar | +------+---------+-------+ 查询得到的结果表: +------+-------------+-------------+-------------+-----+-------------+ | id | Jan_Revenue | Feb_Revenue | Mar_Revenue | ... | Dec_Revenue | +------+-------------+-------------+-------------+-----+-------------+ | 1 | 8000 | 7000 | 6000 | ... | null | | 2 | 9000 | null | null | ... | null | | 3 | null | 10000 | null | ... | null | +------+-------------+-------------+-------------+-----+-------------+ 注意,结果表有 13 列 (1个部门 id 列 + 12个月份的收入列)。
SQL语句:
group by id 会使department表按照id分组,生成一张虚拟表(假想中的表)如下:
- +------+---------+-------+
- | id | revenue | month |
- +------+---------+-------+
- | | 8000 | Jan |
- | 1 | 7000 | Feb |
- | | 6000 | Mar |
- +------+---------+-------+
- | 2 | 9000 | Jan |
- +------+---------+-------+
- | 3 | 10000 | Feb |
- +------+---------+-------+
在虚拟表中,所有id=1的revenue或者month数据都写在了同一个单元格中,如8000、7000、6000都是写在同一单元格内的。真正的表是不能这样写的,所以这种写法只存在于虚拟表中,帮助我们理解。
一个单元格中有多个数据时,case when只会提取当中的第一个数据。以case when month='Feb' then revenue end为例,当id=1时,它只会提取month对应单元格里的第一个数据,即Jan,它不等于Feb,所以找不到Feb对应的revenue,所以返回NULL。(可以试试把我上面答案里的sum()统统去掉,执行结果与预期不一样。错就错在当id=1时,Feb_Revenue和Mar_Revenue的值变成了NULL)。
那该如何解决单元格内含多个数据的情况呢?答案就是使用聚合函数,聚合函数就用来输入多个数据,输出一个数据的。如SUM()或MAX(),而每个聚合函数的输入就是每一个多数据的单元格。
以sum(case when month='Feb' then revenue end) 为例,当id=1时,它提取的Jan、Feb、Mar,从中找到了符合条件的Feb,并最终返回对应的revenue的值,即7000。
写一段 SQL , 报告每个用户的旅行距离。返回的结果表单,以 travelled_distance 降序排列 ,如果有两个或者更多的用户旅行了相同的距离, 那么再以 name 升序排列 。
if(表达式,a,b) 表达式为真返回a,为假返回b。
coalesce(表达式1,表达式2,...)
按照顺序首先执行表达式1,如果不为null则返回表达式1的结果,如果为null,则往下执行表达式2。以此类推。可以用于当返回值为null时的默认返回。
注意 group by 不能换成 group by name ,以为有重名的可能性。
表 Activities
:
+-------------+---------+ | 列名 | 类型 | +-------------+---------+ | sell_date | date | | product | varchar | +-------------+---------+ 此表没有主键,它可能包含重复项。 此表的每一行都包含产品名称和在市场上销售的日期。
编写一个 SQL 查询来查找每个日期、销售的不同产品的数量及其名称。
每个日期的销售产品名称应按词典序排列。
返回按 sell_date
排序的结果表。
查询结果格式如下例所示。
示例 1:
- 输入:
- Activities
表:
+------------+-------------+
| sell_date | product |
+------------+-------------+
| 2020-05-30 | Headphone |
| 2020-06-01 | Pencil |
| 2020-06-02 | Mask |
| 2020-05-30 | Basketball |
| 2020-06-01 | Bible |
| 2020-06-02 | Mask |
| 2020-05-30 | T-Shirt |
+------------+-------------+
输出:
+------------+----------+------------------------------+
| sell_date | num_sold | products |
+------------+----------+------------------------------+
| 2020-05-30 | 3 | Basketball,Headphone,T-shirt |
| 2020-06-01 | 2 | Bible,Pencil |
| 2020-06-02 | 1 | Mask |
+------------+----------+------------------------------+
解释:
对于2020-05-30,出售的物品是 (Headphone, Basketball, T-shirt),按词典序排列,并用逗号 ',' 分隔。
对于2020-06-01,出售的物品是 (Pencil, Bible),按词典序排列,并用逗号分隔。
对于2020-06-02,出售的物品是 (Mask),只需返回该物品名。
SQL
concat():功能:将多个字符串连接成一个字符串,语法:concat(str1, str2,...),返回结果为连接参数产生的字符串,如果有任何一个参数为null,则返回值为null。相当于拼接字符串。
concat(a,b) 输出 ab concat(a, ',' ,b) 输出 a,b
group_concat()
1、功能:将group by产生的同一个分组中的值连接起来,返回一个字符串结果。
2、语法:group_concat( [distinct] 要连接的字段 [order by 排序字段 asc/desc ] [separator '分隔符'] )
说明:通过使用distinct可以排除重复值;如果希望对结果中的值进行排序,可以使用order by子句;separator是一个字符串值,缺省为一个逗号。
患者信息表: Patients
+--------------+---------+ | Column Name | Type | +--------------+---------+ | patient_id | int | | patient_name | varchar | | conditions | varchar | +--------------+---------+ patient_id (患者 ID)是该表的主键。 'conditions' (疾病)包含 0 个或以上的疾病代码,以空格分隔。 这个表包含医院中患者的信息。
写一条 SQL 语句,查询患有 I 类糖尿病的患者 ID (patient_id)、患者姓名(patient_name)以及其患有的所有疾病代码(conditions)。I 类糖尿病的代码总是包含前缀 DIAB1
。
按 任意顺序 返回结果表。
查询结果格式如下示例所示。
示例 1:
- 输入:
- Patients表:
+------------+--------------+--------------+
| patient_id | patient_name | conditions |
+------------+--------------+--------------+
| 1 | Daniel | YFEV COUGH |
| 2 | Alice | |
| 3 | Bob | DIAB100 MYOP |
| 4 | George | ACNE DIAB100 |
| 5 | Alain | DIAB201 |
+------------+--------------+--------------+
输出:
+------------+--------------+--------------+
| patient_id | patient_name | conditions |
+------------+--------------+--------------+
| 3 | Bob | DIAB100 MYOP |
| 4 | George | ACNE DIAB100 |
+------------+--------------+--------------+
解释:Bob 和 George 都患有代码以 DIAB1 开头的疾病。
SQL:select* from patients where conditions regexp "\\bDIAB1";
\\b 第一个\是转义字符,\b匹配单词的开始与结束
13.进店却未进行交易的顾客
表:Visits
+-------------+---------+ | Column Name | Type | +-------------+---------+ | visit_id | int | | customer_id | int | +-------------+---------+ visit_id 是该表的主键。 该表包含有关光临过购物中心的顾客的信息。
表:Transactions
+----------------+---------+ | Column Name | Type | +----------------+---------+ | transaction_id | int | | visit_id | int | | amount | int | +----------------+---------+ transaction_id 是此表的主键。 此表包含 visit_id 期间进行的交易的信息。
有一些顾客可能光顾了购物中心但没有进行交易。请你编写一个 SQL 查询,来查找这些顾客的 ID ,以及他们只光顾不交易的次数。
返回以 任何顺序 排序的结果表。
查询结果格式如下例所示。
示例 1:
+----------+-------------+ | visit_id | customer_id | +----------+-------------+ | 1 | 23 | | 2 | 9 | | 4 | 30 | | 5 | 54 | | 6 | 96 | | 7 | 54 | | 8 | 54 | +----------+-------------+
输入: VisitsTransactions
+----------------+----------+--------+ | transaction_id | visit_id | amount | +----------------+----------+--------+ | 2 | 5 | 310 | | 3 | 5 | 300 | | 9 | 5 | 200 | | 12 | 1 | 910 | | 13 | 2 | 970 | +----------------+----------+--------+ 输出: +-------------+----------------+ | customer_id | count_no_trans | +-------------+----------------+ | 54 | 2 | | 30 | 1 | | 96 | 1 | +-------------+----------------+ 解释: ID = 23 的顾客曾经逛过一次购物中心,并在 ID = 12 的访问期间进行了一笔交易。 ID = 9 的顾客曾经逛过一次购物中心,并在 ID = 13 的访问期间进行了一笔交易。 ID = 30 的顾客曾经去过购物中心,并且没有进行任何交易。 ID = 54 的顾客三度造访了购物中心。在 2 次访问中,他们没有进行任何交易,在 1 次访问中,他们进行了 3 次交易。 ID = 96 的顾客曾经去过购物中心,并且没有进行任何交易。 如我们所见,ID 为 30 和 96 的顾客一次没有进行任何交易就去了购物中心。顾客 54 也两次访问了购物中心并且没有进行任何交易。
SQL:select customer_id,count(customer_id) count_no_trans from visits v left join transactions t on v.visit_id=t.visit_id where amount is null group by customer_id;
编写一个 SQL 查询来修复名字,使得只有第一个字符是大写的,其余都是小写的。
select user_id, concat(upper(left(name,1)),lower(substring(name,2))) name from users order by user_id;
1 concat() 函数
CONCAT 可以将多个字符串拼接在一起。
2 left(str, length) 函数
从左开始截取字符串,length 是截取的长度。
3 upper(str) 与 lower(str)
UPPER(str) 将字符串中所有字符转为大写
LOWER(str) 将字符串中所有字符转为小写
4 substring(str, begin, end)
截取字符串,end 不写默认为空。
SUBSTRING(name, 2) 从第二个截取到末尾,注意并不是下标,就是第二个。
表:Products
+-------------+---------+ | Column Name | Type | +-------------+---------+ | product_id | int | | store1 | int | | store2 | int | | store3 | int | +-------------+---------+ 这张表的主键是product_id(产品Id)。 每行存储了这一产品在不同商店store1, store2, store3的价格。 如果这一产品在商店里没有出售,则值将为null。
请你重构 Products
表,查询每个产品在不同商店的价格,使得输出的格式变为(product_id, store, price)
。如果这一产品在商店里没有出售,则不输出这一行。
输出结果表中的 顺序不作要求 。
查询输出格式请参考下面示例。
示例 1:
输入: Products table: +------------+--------+--------+--------+ | product_id | store1 | store2 | store3 | +------------+--------+--------+--------+ | 0 | 95 | 100 | 105 | | 1 | 70 | null | 80 | +------------+--------+--------+--------+ 输出: +------------+--------+-------+ | product_id | store | price | +------------+--------+-------+ | 0 | store1 | 95 | | 0 | store2 | 100 | | 0 | store3 | 105 | | 1 | store1 | 70 | | 1 | store3 | 80 | +------------+--------+-------+ 解释: 产品0在store1,store2,store3的价格分别为95,100,105。 产品1在store1,store3的价格分别为70,80。在store2无法买到。
SQL
1. 列转行, 不考虑去重:union all, 考虑去重,用union
2. 行转列: case when(sum+if)
表: Employees
+-------------+---------+ | 列名 | 类型 | +-------------+---------+ | employee_id | int | | name | varchar | | salary | int | +-------------+---------+ employee_id 是这个表的主键。 此表的每一行给出了雇员id ,名字和薪水。
写出一个SQL 查询语句,计算每个雇员的奖金。如果一个雇员的id是奇数并且他的名字不是以'M'开头,那么他的奖金是他工资的100%,否则奖金为0。
Return the result table ordered by employee_id
.
返回的结果集请按照employee_id
排序。
查询结果格式如下面的例子所示。
示例 1:
输入: Employees 表: +-------------+---------+--------+ | employee_id | name | salary | +-------------+---------+--------+ | 2 | Meir | 3000 | | 3 | Michael | 3800 | | 7 | Addilyn | 7400 | | 8 | Juan | 6100 | | 9 | Kannon | 7700 | +-------------+---------+--------+ 输出: +-------------+-------+ | employee_id | bonus | +-------------+-------+ | 2 | 0 | | 3 | 0 | | 7 | 7400 | | 8 | 0 | | 9 | 7700 | +-------------+-------+ 解释: 因为雇员id是偶数,所以雇员id 是2和8的两个雇员得到的奖金是0。 雇员id为3的因为他的名字以'M'开头,所以,奖金是0。 其他的雇员得到了百分之百的奖金。
SQL:
表: Logins
+----------------+----------+ | 列名 | 类型 | +----------------+----------+ | user_id | int | | time_stamp | datetime | +----------------+----------+ (user_id, time_stamp) 是这个表的主键。 每一行包含的信息是user_id 这个用户的登录时间。
编写一个 SQL 查询,该查询可以获取在 2020
年登录过的所有用户的本年度 最后一次 登录时间。结果集 不 包含 2020
年没有登录过的用户。
返回的结果集可以按 任意顺序 排列。
查询结果格式如下例。
示例 1:
输入: Logins 表: +---------+---------------------+ | user_id | time_stamp | +---------+---------------------+ | 6 | 2020-06-30 15:06:07 | | 6 | 2021-04-21 14:06:06 | | 6 | 2019-03-07 00:18:15 | | 8 | 2020-02-01 05:10:53 | | 8 | 2020-12-30 00:46:50 | | 2 | 2020-01-16 02:49:50 | | 2 | 2019-08-25 07:59:08 | | 14 | 2019-07-14 09:00:00 | | 14 | 2021-01-06 11:59:59 | +---------+---------------------+ 输出: +---------+---------------------+ | user_id | last_stamp | +---------+---------------------+ | 6 | 2020-06-30 15:06:07 | | 8 | 2020-12-30 00:46:50 | | 2 | 2020-01-16 02:49:50 | +---------+---------------------+ 解释: 6号用户登录了3次,但是在2020年仅有一次,所以结果集应包含此次登录。 8号用户在2020年登录了2次,一次在2月,一次在12月,所以,结果集应该包含12月的这次登录。 2号用户登录了2次,但是在2020年仅有一次,所以结果集应包含此次登录。 14号用户在2020年没有登录,所以结果集不应包含。
SQL:
表: Employees
+-------------+---------+ | Column Name | Type | +-------------+---------+ | employee_id | int | | name | varchar | +-------------+---------+ employee_id 是这个表的主键。 每一行表示雇员的id 和他的姓名。
表: Salaries
+-------------+---------+ | Column Name | Type | +-------------+---------+ | employee_id | int | | salary | int | +-------------+---------+ employee_id is 这个表的主键。 每一行表示雇员的id 和他的薪水。
写出一个查询语句,找到所有 丢失信息 的雇员id。当满足下面一个条件时,就被认为是雇员的信息丢失:
返回这些雇员的id employee_id
, 从小到大排序 。
查询结果格式如下面的例子所示。
示例 1:
输入: Employees table: +-------------+----------+ | employee_id | name | +-------------+----------+ | 2 | Crew | | 4 | Haven | | 5 | Kristian | +-------------+----------+ Salaries table: +-------------+--------+ | employee_id | salary | +-------------+--------+ | 5 | 76071 | | 1 | 22517 | | 4 | 63539 | +-------------+--------+ 输出: +-------------+ | employee_id | +-------------+ | 1 | | 2 | +-------------+ 解释: 雇员1,2,4,5 都工作在这个公司。 1号雇员的姓名丢失了。 2号雇员的薪水信息丢失了。
SQL:
思路:雇员的姓名丢失了或者雇员的薪水信息丢失,都会导致employee_id 在 employees 和salaries 的并集表里面仅出现一次
注意: 每个派生表都需要有自己的别名,不然执行不了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。