Mysql|数据分析搞懂这15道SQL题目笔试就稳了

这是最近数分面试小伙伴遇到的mysql面试题,在网上查了一下,没有完整答案,所以特意整理了一下,帮助正准备或已经在面试中的伙伴,每道题不止一种写法,不保证完全正确,供参考思路哈~ 欢迎留言交流,共同进步~

第一题:

现有以下三张表

CREATE TABLE `hospital` ( `HospitalId` varchar(36) NOT NULL,
 `HospitalName` varchar(100) DEFAULT NULL, 
`ProvinceName` varchar(45) DEFAULT NULL,
 `CityName` varchar(45) DEFAULT NULL, 
`Disabled` bit(1) NULL DEFAULT 0, 
PRIMARY KEY (`HospitalId`)
) COMMENT='医院表'
;
 
 CREATE TABLE `product` (
   `ProductId` varchar(36) NOT NULL,
   `ProductName` varchar(100) NULL,
   `Price` decimal(10, 2) NOT NULL COMMENT '单价',
   PRIMARY KEY (`ProductId`)
 ) COMMENT='产品表'
 ;
 
 CREATE TABLE `sales` (
   `SalesId` varchar(36) NOT NULL,
   `HospitalId` varchar(36) NOT NULL,
   `Period` date NOT NULL COMMENT '日期yyyy/mm/dd',
   `ProductId` varchar(36) NOT NULL,
   `SalesVolume` decimal(10, 2) NOT NULL COMMENT '销售数量',
   PRIMARY KEY (`SalesId`),
   CONSTRAINT `fk_hospitalid` FOREIGN KEY (`HospitalId`) REFERENCES `hospital` (`HospitalId`),
   CONSTRAINT `fk_productid` FOREIGN KEY (`ProductId`) REFERENCES `product` (`ProductId`)
 ) COMMENT='销量表'
 ;

写出SQL语句:查询产品名称=“A药品”,在北京医院2018~2019两年的销售“金额”,排除两年销售金额总和>1000000的医院,要求查询结果如下表。

思路:
1、首先将城市是北京,产品名称是A药品, 2018和2019年销售额之和大于 1000000 的医院id 和 医院名查询出来
2、考虑按月份显示销售额,这里为了代码简洁直接用了年份,通过 sum(if())算出各个医院的每年的销售额
3、最后将两个子查询 按照 医院id进行连接,得到符合条件的最终结果

答案:

SELECT * FROM
(SELECT
    hospitalid,hospitalname
FROM
    hospital WHERE cityname='北京' AND hospitalid IN (
    select hospitalid  from product LEFT JOIN sales ON product.productid = sales.productid
WHERE productname='a药品' AND YEAR(period) in (2018,2019)
GROUP BY hospitalid
HAVING SUM(price * salesvolume)  > 1000000
    )) as t1
INNER JOIN
(
SELECT hospitalid,
sum(if(YEAR(period) = '2018',price * SalesVolume ,0)) as '2018',
sum(if(YEAR(period) = '2019',price * SalesVolume ,0)) as '2019'
 FROM sales LEFT JOIN product on sales.ProductId = product.ProductId GROUP BY hospitalid) as t2
 
ON t1.hospitalid = t2.hospitalid

运行结果

第二题(与第一题同样的数据):

写出SQL语句,查询题1的销量表中2019年任意连续三个月销售额都>0的医院。
返回字段:HospitalId,SalesMonth(2019年销量>0的所有月份,逗号隔开)

思路:
1、写一个子查询,筛选出2019年,销售额>0的医院,窗口函数按医院id进行分组 按医院ID,日期排序,并建辅助列 row_num
2、通过第一个子查询得到的月份Period_month和辅助列row_num,做减法(目的是通过相等的差,判断是否连续)
3、对 两者之差 sig_num ,做个分组,count 大于等于3,即符合条件,最后用GROUP_CONCAT 将连续月份拼接起来

答案:

SELECT
    Hospitalid,
    count( sig_num ) AS count_sig_num,
    GROUP_CONCAT( Period_month ) 
FROM
    (
    SELECT
        Hospitalid,
        Period_month,
        row_num,
        CONVERT ( Period_month, signed ) - CONVERT ( row_num, signed ) AS sig_num 
    FROM
        (
        SELECT
            Hospitalid,
            MONTH ( Period ) Period_month,
            row_number() over ( PARTITION BY Hospitalid ORDER BY Hospitalid, Period ) row_num 
        FROM
            sales 
        WHERE
            YEAR ( Period ) = '2019' 
            AND salesvolume > 0 
        ) t1 
    ) t2 
GROUP BY
    Hospitalid,
    sig_num 
HAVING
    count_sig_num >= 3;
运行结果

第三题:

以下是微信聊天记录表

 CREATE TABLE `wechat` (
   `WechatId` varchar(36) NOT NULL,
   `WechatFriendId` varchar(36) NOT NULL COMMENT '每个ID表示一对好友',
   `ChatTime` datetime NOT NULL COMMENT '聊天时间',
   `IsSend` bit NOT NULL COMMENT '我方发送:1,用户回复:0',
   `Content` text NULL COMMENT '内容',
   PRIMARY KEY (`WechatId`),
 ) COMMENT='微信聊天';

写出SQL语句:按月统计2020年的微信回复率

发送次数 = 一组好友在一个自然天内的所有发送记录计为1次。

回复率计算公式 =(发送次数在两个自然天内被回复)/发送次数*100%

思路:
1、先统计 2020年每月的微信发送次数(注意每个日然人一日发送多次记为1次)
2、再统计 2020年每月的微信回复的次数(注意这里回复和发送的用户要对应,还有个重要条件48小时内回复)
3、算出 回复率 = 回复次数/发送次数

答案:

with send as(
SELECT  DATE_FORMAT(t1.ChatTime,'%Y-%m') cm,COUNT(1) send_cnt
FROM (
            select 
             ChatTime,
             count(distinct WechatFriendId) send_cnt
            from wechat
            where IsSend = 1 and year(ChatTime) = '2020'
            group by 1) t1
GROUP BY 1
 ),
 response as(
SELECT DATE_FORMAT(a.ChatTime,'%Y-%m') cm, 
     count(distinct a.WechatFriendId) resp_cnt
from
     (select WechatFriendId,ChatTime from wechat where year(ChatTime) = '2020' and IsSend=1) a
left join
     (select WechatFriendId,ChatTime from wechat where year(ChatTime) = '2020' and  IsSend=0) b
on
     a.WechatFriendId = b.WechatFriendId
where 
     datediff(b.ChatTime, a.ChatTime) <= 2 AND datediff(b.ChatTime, a.ChatTime) >= 0
 group by 1
 )
 select 
     cm, resp_cnt,send_cnt,concat(round(resp_cnt/send_cnt,4)*100,'%') as '回复率'
 from
     send join response using(cm)
运行结果

未完。。。 持续更新中。。。

你可能感兴趣的:(Mysql|数据分析搞懂这15道SQL题目笔试就稳了)