查看原文
其他

3道SQL面试题,总结常考知识点!

小小 小小的SQL学习笔记 2022-10-28
点击蓝字关注我吧大家好,我是小小,一个工作了3年的数据分析师。我在入门SQL时走了不少弯路,所以总结了一些有效的学习经验在这里分享给大家,在学习SQL的路上我们一起相互陪伴吧~


SQL面试问题旨在评估应聘者的技术和解决问题的能力。因此对于应聘者来说,关键在于不仅要根据样本数据编写出正确的查询,而且还要像对待现实数据集一样考虑各种场景和边缘情况


今天,小小准备了3道SQL题以及解析,测测你的SQL能力。



01


第1题:写一个SQL函数,能将一串字符串按指定的分隔符拆分成行。比如给定字符串“查询,入库,出库,移库,盘点,设置”,查询出来的结果是:



审题:这是一道典型的Split函数题。看过一些写法,可以一段一段地截取,可以使用反转等等,但是核心的知识点就是Index。


做题:下面是我的写法,仅供参考。

CREATE FUNCTION [dbo].[Split](@Text NVARCHAR(4000),@SplitSymbol NVARCHAR(4000))
    RETURNS @ResultTable TABLE ([VALUE] NVARCHAR(4000))
AS  
BEGIN
    --变量定义
    DECLARE @StartIndex INT         --开始位置
    DECLARE @FindIndex INT         --找到位置
    DECLARE @Content NVARCHAR(4000) --找到内容
    
    --变量初始化
    SET @StartIndex=1                --T-SQL查找位置是从1开始的
    SET @FindIndex=0  
    
    --循环查找字符串分割符
    WHILE (@StartIndex<=LEN(@Text))
    BEGIN
        --返回查找位置
        SELECT @FindIndex=CHARINDEX(@SplitSymbol,@Text,@StartIndex)

        --查找位置返回0表示已查找完毕
        IF (ISNULL(@FindIndex,0)=0)
        BEGIN
            SET @FindIndex=LEN(@Text)+1
        END
         
        --截取字符串
        SET @Content=LTRIM(RTRIM(SUBSTRING(@Text,@StartIndex,@FindIndex-@StartIndex)))

        --初始化下次开始位置
        SET @StartIndex=@FindIndex+1

        --找到值插入结果表
        INSERT INTO @ResultTable ([VALUE]) VALUES (@Content)
    END

    RETURN
END


执行:

SELECT * FROM Split('查询,入库,出库,移库,盘点,设置',',')



02


现有某地区某天的选举投票数据,ge数据表为投票记录,Candidates数据表候选人信息,根据已有数据用SQL知识解答下列问题:



第2题:随机抽选2名给Trump投票的投票人以及联系方式(结果包含name以及phone_number)。 


 解析 


本题主要考察的是“随机”的概念,用到rand()函数,并根据rand()进行排序。括号中不需要填写任何内容,否则就不是“随机”了。


select name, phone_number
from ge
where vote = 'RP1'
order by rand()
limit 2;


第3题:查询出投票时间截止到09:21:18时,超过5票的候选人信息以及票数。


 解析 


本题主要考察的是表关联、where与having的区别、以及聚合函数与group by的使用,当然也可以用子查询的方式,以下方法较为简洁。需要注意的是,在不用子查询的情况下,在where中不能筛选同一级select后面的count()条件,这里涉及到SQL语句执行顺序,后面具体再单独讲,也可以自己去了解一下~


select C.Candidate, C.gender, C.party, count(ge.ssn)
from ge
    join
    Candidates C
    on ge.vote = C.candidateId
where ge.voting_time <= '09:21:18' 
group by C.Candidate
having count(ge.ssn)>5;


第4题:查询出投票时间截止到09:21:18时,连续获得3票及3票以上的候选人姓名以及获得投票的id,name,voting_time,连续获得投票的次数。


 解析 


这道题是考察“连续性”问题,是面试中经常考的一类题,主要是考察子查询、窗口函数的熟练使用,具体可以分为以下三步:


第一步:先用id减去根据vote分组按照id排序之后的序号,获得一个差值。如果同一个vote的差值相等,则说明相等的部分是连续的,代码实现与结果如下:


select id
    ,name
    ,voting_time
    ,vote
    ,id - row_number() over(partition by vote order by id,voting_time) as
D_value
from ge
where ge.voting_time <= '09:21:18' 
order by id



第二步:计算连续的次数,这里用窗口函数count(1) over(...)来进行计算,根据差值与同一vote进行分组计算,这里没有在over()里进行排序,是因为后面需要查询出这连续的一组数据。具体代码以及结果如下:


select D.id
    ,D.name
    ,D.voting_tim
    ,D.vote
    ,count(1) over(partition by D.D_value,D.vote) as times
from(
    select id
          ,name
          ,voting_time
          ,vote
          ,id - row_number() over(partition by vote order by
id,voting_time) as D_value
    from ge
    where ge.voting_time <= '09:21:18' 
-- order by id
)D
order by id;



第三步:查询出最后结果:根据题目要求,筛选出3票及3票以上的结果。


select c.Candidate, t.id, t.name, t.voting_time, t.times
from
    (select D.id,D.name,D.voting_time,D.vote,count(1) over(partition by D.D_value,D.vote) as times
    from(
        select id
              ,name
              ,voting_time
              ,vote
              ,id - row_number() over(partition by vote order by id,voting_time) as D_value
        from ge
        where ge.voting_time <= '09:21:18' 
-- order by id
    ) D) t
-- order by id
    left join
    Candidates c
    on t.vote = c.candidateId
where times >= 3;


注意:这道题也可以用其他方法,比如表关联,但如果是次数太多,那么表关联的次数也会很多,所以在次数太多的情况下不建议用表关联,记住这个方法就可以了~


近期,小小想邀请6年电商行业数据分析师经验、母婴独角兽公司数据产品经理阿坤老师给大家分享SQL知识,但是时间、主题未定,大家可以先在B站上观看一下阿坤老师讲解的《大厂MySQL面试真题解析》,点击图片听课:

小伙伴们还有什么想看的知识点或者学习求职过程中遇到了什么问题,都可以在公众号后台留言哦,小小一定知无不答




小小的福利合集,后台回复:


【安装包】——领取《MySQL安装包》


【7】——领取《SQL数据分析常用语句》


【SQL】——领取《SQL学习路径思维导图》


【书籍】——领取《SQL书籍》


【50】——领取《MySQL经典50题》


【导图】——领取《MySQL必知必会导图》


【手册】——领取《MySQL基础查询手册》


【21】——领取《MySQL性能优化的21个实践》


【s1】——领取《SQL21天自学通》



小小的心愿:整理不易,分享、点赞、在看,三连一下!



- END -

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存