这个是2024年1月中旬面的,当时准备的不充分,就凉了。emmm,现在发一下。
1、上一份实习了4个月之后为什么不继续实习了?
2、我看你上一份实习主要是做机器学习是吧?你机器学习使用的是什么模型?
(1)具体调用哪些算法你有研究过吗?
(2)你的这个项目主要是做什么工作?
(3)是不是大概就是从数据库拿数据,然后对数据进行清洗,然后在进行自动化调度、自动化训练对吧?
(4)你数据库拿数据是使用sql拿吗,还是使用Python拿?
(5)mysql和heidisql的区别是什么?
(6)你实习当中最多的是使用python对吧
3、你这个大语言模型是调研还是在公司里面准备使用?
(1)那就是这个大语言模型已经使用上了对吧?
对,有嵌入系统
(2)你们这个大语言模型的问答主要是做什么问答?
代码提示、文档查询方面的
(3)面试官点评:这个相当于是大语言模型的使用
(4)你有使用过文心一言吗?你觉得文心一言和你们部署的大模型有什么差别?你有没有做过一些对比?
(5)写过shell脚本吗?linux使用过一些对吧?
4、SQL用的多吗?Python用的多?
5、有没有写过一些面向对象的Python脚本库?
6、数据库你用过哪些?
7、大数据你用过哪些?
8、你spark用过多长时间?
9、接下来是4道sql的题目
(1)100*(b-a)/a
(2)我想把查询出来最近7天的日期,返回值是一列,并且将最近的倒数第三天的日期返回在第一行,我要返回七行数据,并且第一行是第三天的日期。
SELECT DATE_FORMAT(date_column, '%Y-%m-%d') AS recent_dates
FROM your_table
WHERE date_column >= CURDATE() - INTERVAL 7 DAY
ORDER BY date_column DESC
LIMIT 7;
10、开始问一些关于SQL的问题
(1)你知道SQL的执行顺序是什么吗?
书写顺序:
SELECT -> DISTINCT -> FROM -> JOIN -> ON -> WHERE -> GROUP BY -> HAVING -> ORDER BY -> LIMIT
执行顺序:
FROM -> JOIN -> ON -> WHERE -> GROUP BY -> HAVING -> SELECT -> DISTINCT -> ORDER BY -> LIMIT
执行顺序解释:
1.from 要做数据分析,得先有个表
2.join 一个表可能还不够,两个表甚至多个表都可以,关联条件啥也先不用,可以都来个笛卡儿积先
3.on 在诸多表左右连接后,设定两个表之间的关联键,把不符合条件的全部筛掉
4.where 上三步整合各表,形成一个统一大表;在此大表上,设置筛选条件
5.group by 把指定字段相同的行组合在一起,其余没有加入group by的字段,可以用聚合函数如max/min等合并
6.having 在group by了之后,再度指定筛选条件;注意where和having是不同的,主要在于中间多了group by
7.select 在行层面的处理暂告一段落,在列层面再来一波
8.distinct 指定字段去重
9.order by 指定字段排序,升降序
10.limit 指定哪些行
(2)窗口函数主要做什么?
窗口函数是OLAP函数,是对数据库数据进行实时分析处理。每条记录都要在此窗口内执行函数。
(3)你主要用过哪些窗口函数?
聚合、跨行取值、排名函数
(4)rank、row_number、dense_rank三者的区别?
(5)count(*)和count(列名)和count(1)的区别?
执行效果上:
count(*)包括了所有的列,相当于行数,在统计结果的时候,不会忽略为NULL的值。
count(1)包括了忽略所有列,用1代表代码行,在统计结果的时候,不会忽略为NULL的值。
count(列名)只包括列名那一列,在统计结果的时候,会忽略列值为空(这里的空不是指空字符串或者0,而是表示null)的计数,即某个字段值为NULL时,不统计。
执行效率上:
列名为主键,count(列名)会比count(1)快
列名不为主键,count(1)会比count(列名)快
如果表多个列并且没有主键,则 count(1 的执行效率优于 count()
如果有主键,则 select count(主键)的执行效率是最优的
如果表只有一个字段,则 select count()最优。
(6)你有使用过mysql索引吗?
(7)mysql如何查看索引?
查看表的索引:
show index from table_name(表名)
(8)写了一个sql,如何查看是否有命中索引?
MySQL提供了EXPLAIN语句来查看查询的执行计划,通过执行计划我们可以判断索引是否被命中。EXPLAIN语句可以使用以下方式执行:
explain select * from table_name where column_name='value';
执行上述语句后,MySQL会返回一张表,其中包含执行计划的相关信息。我们可以通过查看表中的一些字段来判断索引是否被命中。
根据返回的执行计划,我们可以采用以下几种方法来判断索引是否命中:
检查type字段:如果type字段的值是index或range,表示索引被命中;如果type字段的值是ALL,则表示索引未被命中。
检查possible_keys字段和key字段:如果possible_keys字段和key字段都不为空,且其值相同,表示索引被命中;如果possible_keys字段和key字段都为空,表示索引未被命中。
检查Explain Extra字段:如果Extra字段中包含Using index或Using where,表示索引被命中;如果Extra字段中包含Using temporary或Using filesort,表示索引未被命中。
(9)联合索引你知道吗?联合索引的匹配原则是什么?
联合索引(Compound Index)是一个包含多个列的索引。联合索引可以在多个列上同时进行查询优化,有助于提高多列查询的性能。在创建联合索引时,需要考虑列的顺序,因为索引的使用受到最左前缀原则的限制。
对于索引中的字段,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。
11、问一些Python的问题
(1)Python的局部变量和全局变量?
全局变量:所有函数之外定义的变量
局部变量:函数内部定义的变量 或者代码块里的变量
1.函数内部的变量名如果第一次出现,且出现在=前面,即被视为定义了一个局部变量,不管全局域中有没有该变量名,函数中使用的将是局部变量。
(即声明了一个新的局部变量。如果这个变量名字和全部变量名字相同,那么局部变量名字会覆盖全局变量名字。
#[demo1]
num = 100
def func():
newValue = 123 #一个全新的局部变量newValue
print(newValue)
func() #输出局部变量newValue 即新的局部变量
#[demo2]
num = 100
def func():
num= 123 #声明一个全新的局部变量num,虽然名字和外界的全部变量相同 但是是新的一个变量且是局部有效的。屏蔽了外面的同名的全部变量
print(num)
func() #输出局部变量num=123 即新的局部变量。
(2)并发和并行的区别?(spark或者Python基本都会涉及这两个概念)
并发是指一个处理器同时处理多个任务。
并行是指多个处理器或者是多核的处理器同时处理多个不同的任务。
并发是逻辑上的同时发生(simultaneous),而并行是物理上的同时发生。
来个比喻:并发是一个人同时吃三个馒头,而并行是三个人同时吃三个馒头。
(3)Python里面迭代器和生成器的理解?
生成器是一种特殊类型的迭代器,但它的定义更为简单,可以直接使用函数语法。
(4)Python当中yield关键词解释一下?(是和迭代器有关的)
(5)Python正则表达式当中match和search的区别是什么?
re.match(pattern, string):
这个方法从字符串的开头开始匹配模式。
只在字符串的开头位置进行匹配,如果字符串开头没有匹配的模式,则返回None。
适合用于检查字符串是否以特定模式开头。
import re
pattern = re.compile(r'\d+')
result = pattern.match('123abc')
if result:
print("Match found:", result.group())
else:
print("No match at the beginning of the string.")
re.search(pattern, string):
这个方法在整个字符串中搜索匹配的模式。
可以在字符串的任意位置找到匹配,而不仅仅是在开头。
返回第一个匹配的对象,如果没有找到匹配的模式,则返回None。
import re
pattern = re.compile(r'\d+')
result = pattern.search('abc123xyz')
if result:
print("Match found:", result.group())
else:
print("No match in the entire string.")
(6)正则表达式当中的贪婪匹配和非贪婪匹配的区别?
贪婪匹配:
在贪婪匹配模式下,量词会尽可能多地匹配字符。例如,* 将匹配尽可能多的字符,+ 也会尽可能多地匹配,而 ? 会尽可能匹配。
import re
text = "abc123def456"
pattern = re.compile(r'\d+')
match = pattern.search(text)
print(match.group()) # 输出: 123
在上面的例子中,\d+ 是贪婪匹配,它尽可能多地匹配数字字符,因此匹配到了整个数字序列 “123”。
非贪婪匹配:
在非贪婪匹配模式下,量词会尽可能少地匹配字符。在量词后加上 ? 可以使其变成非贪婪匹配。
import re
text = "abc123def456"
pattern = re.compile(r'\d+?')
match = pattern.search(text)
print(match.group()) # 输出: 1
在上面的例子中,\d+? 是非贪婪匹配,它会尽可能少地匹配数字字符,因此只匹配到了第一个数字 “1”。
总体来说,贪婪匹配尽可能多地匹配字符,而非贪婪匹配尽可能少地匹配字符。这在处理模糊匹配时,特别是需要匹配最短或最长字符串时非常有用。
(7)类和面向对象的区别?
类(Class):
类是一种抽象的数据类型,是对相似对象的共同特征和行为的抽象描述。它定义了对象的属性(数据成员)和方法(成员函数)。
类可以看作是创建对象的模板或蓝图,它定义了对象应该具有的属性和行为。
类本身并不占用内存空间,而是通过类创建的对象占用内存空间。
示例代码:
class Car:
def __init__(self, brand, model):
self.brand = brand
self.model = model
def drive(self):
print(f"{self.brand} {self.model} is driving.")
# 创建一个Car类的对象
my_car = Car("Toyota", "Camry")
# 调用对象的方法
my_car.drive()
对象(Object):
对象是类的实例,是类的具体实体。它是根据类的定义创建的,拥有类定义的属性和行为。
对象是具体的、实际存在的,占用内存空间。
一个类可以创建多个对象,每个对象都是独立的,拥有自己的属性值。
示例代码:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def speak(self):
print(f"{self.name} is speaking.")
# 创建两个Person类的对象
person1 = Person("Alice", 25)
person2 = Person("Bob", 30)
# 调用对象的方法
person1.speak()
person2.speak()
总体而言,类是一种抽象的概念,描述了对象的属性和行为;而对象是类的实例,是具体存在的实体,拥有类定义的属性和行为。类和对象的使用使得代码更加模块化、可维护,同时提高了代码的重用性。
(8)Python当中在写class的时候,有一个self,这个你见过吗?
(9)dataframe当中如果要查看所有的数据要怎么写?
在使用 pandas 库中的 DataFrame 时,要查看所有的数据,可以使用 print() 函数或直接输入 DataFrame 的名称。如果 DataFrame 中的数据量较大,为了方便查看,可以使用以下方法:
使用 print() 函数:
import pandas as pd
# 假设 df 是你的 DataFrame
df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
# 使用 print() 函数查看所有的数据
print(df)
(10)Python当中的异常,try,catch
(11)python当中异常,如果想定位到具体的哪一行报错了,我需要怎么办?
查看异常信息:
当程序发生异常时,Python会打印出异常信息,包括异常的类型、描述以及发生异常的行号。例如:
try:
# 你的代码
except Exception as e:
print(f"An error occurred: {e}")
在异常信息中,会有类似于 File “your_file.py”, line 10 的信息,其中 your_file.py 是发生异常的文件名,而 line 10 是异常发生的行号。通过这些信息,你可以迅速定位到具体报错的位置。
使用调试器:你可以使用Python的调试器(如pdb)来逐行执行代码并查看每一步的执行情况。在发生异常的地方设置断点,然后逐步执行,直到
发现报错的行。以下是一个简单的例子:
import pdb
try:
# 你的代码
except Exception as e:
pdb.post_mortem()
当异常发生时,程序会停在异常发生的地方,然后你可以使用调试器命令(如 n 表示下一步,c 表示继续执行,等等)来逐步查看代码的执行过程。
使用日志记录:在程序中添加适当的日志记录语句,以便在运行时查看程序执行的详细信息。通过查看日志,你可以了解程序执行到哪一步时发生了异常。例如:
import logging
logging.basicConfig(level=logging.DEBUG)
try:
# 你的代码
except Exception as e:
logging.exception("An error occurred")
运行后,你可以查看日志输出,找到异常发生的位置。
注:面试官想要招一个写Python脚本和pyspark的人,周五中午HR突然打电话问了一下基本情况,下午就一面,比较突然,没啥准备,也是自己基础不行。