Linux, Jenkins, AWS, SRE, Prometheus, Docker, Python, Ansible, Git, Kubernetes, Terraform, OpenStack, SQL, NoSQL, Azure, GCP, DNS, Elastic, Network, Virtualization. DevOps Interview Questions
ℹ️ 本仓库包含各种 DevOps 相关主题的面试问题
📊 当前有 413 个问题
⚠️ 你不需要知道回答这个仓库的所有问题。 DevOps并不是知道一切:)
📄 不同的面试官专注于不同的事情。 有些人将重点放在你的简历上,而另一些人可能将重点放在方案问题或特定的技术问题上。 在这个仓库,我尽力覆盖各种类型的DevOps问题,供你练习和测试你的知识
📝 你可以通过PR来添加更多问题和答案:)
开发人员经常将代码集成到共享仓库中的一种开发实践。 它的范围可以从每天或每周进行几次更改,到大规模在一个小时内进行几次更改。
验证每段代码(更改/补丁),以使更改可以安全地合并。 如今,使用自动构建来确保代码可以集成的测试更改是一种常见的做法。 它可以是一个运行在不同级别(单元,功能等)的多个测试的构建,也可以是所有或某些必须通过以将更改合并到存储库中的多个单独的构建。
你可以使用以下一项或全部:
* 成熟与尖端
* 社区规模
* 体系结构方面-代理与无代理,主控与无主控等
在可变的基础架构原则中,更改将应用到现有基础架构之上并随着时间的推移而变化
基础架构建立了变化的历史。 Ansible,Puppet和Chef这些工具
遵循可变的基础架构原则。
在不变的基础架构原则中,每项更改实际上都是新的基础架构。 所以改变
到服务器将导致新服务器而不是更新服务器。 Terraform是
遵循不变的基础架构原则的一个例子。
当配置和软件完全相同的服务器环境中的某个服务器上发生配置漂移
或服务器正在应用其他服务器无法获得的更新或配置,并且随着时间的推移,这些服务器将变为
略有不同。
这种情形可能会导致难以识别和重现的错误。
注意:交叉依赖是指你对单独的项目进行了两个或多个更改,并且你希望在相互构建中对其进行测试,而不是分别测试每个更改。
IAAS
PAAS
SAAS
边缘位置基本上是内容传递网络,它缓存数据并确保较低的延迟和更快地传递给任何位置的用户。 他们位于世界主要城市。
停止实例,使其实例类型与所需的RAM匹配,然后启动实例。
应用层:用户端(HTTP在这一层)
表示层:在应用程序层实体之间建立上下文(加密在这一层)
会话层:建立,管理和终止连接
传输层:将可变长度的数据序列从源传输到目标主机(TCP和UDP在这一层)
网络层:将数据报从一个网络传输到另一个网络(IP 层在这里)
数据链接层:提供两个直接连接的节点之间的链接(MAC在这一层)
物理层:数据连接的电气和物理规格(比特在这一一层)
广播:向网络中的所有人发送消息。 地址ff:ff:ff:ff:ff:ff:ff用于广播。
使用广播的两个常见协议是ARP和DHCP。
组播:向一组订户发送消息。 它可以是一对多或多对多。
CSMA / CD代表载波侦听多路访问/冲突检测。
它的主要重点是管理对共享媒体/总线的访问,在该共享媒体/总线上,在给定的时间点只能传输一个主机。
CSMA / CD算法:
00110011110100011101
rm
完成同样的结果吗?)df
你会得到 "找不到命令". 可能出现什么问题以及如何修复它?你能使用命令 cron
和 at
.
对于cron,使用以下格式安排任务:
任务存储在cron文件中。
通常,你将安排批处理作业。
使用 chmod
命令.
777 - 所有人有读和写和可执行权限(意味着你很懒)
644 - 拥有者有读和写的权限、其他人只有读权限
750 - 拥有者有所有权限, 组成员可以读和执行权限、其他人没有权限
dstat -t
非常适合辨别网络和磁盘问题。
netstat -tnlaup
可用于查看哪些进程在哪些端口上运行。
lsof -i -P
可以用于与netstat相同的目的。
ngrep -d any metafilter
用于将正则表达式与数据包的载荷相匹配。
tcpdump
用于捕获数据包
wireshark
与tcpdump相同的概念,但带有GUI(可选)。
dstat -t
非常适合辨别网络和磁盘问题。
opensnoop
可以用来查看正在系统上打开哪些文件(实时)。
strace
非常适合了解你的程序的功能。 它打印你的程序执行的每个系统调用。
top
显示每个进程消耗多少CPU占比
perf
是采样分析器的理想选择,通常来说,找出哪些CPU周期被“浪费”了
flamegraphs
非常适合CPU消耗可视化(http://www.brendangregg.com/flamegraphs.html)
top
检查是否有任何资源消耗你的CPU或RAM。dstat -t
来检查它是否与磁盘或网络有关。iostat
检查 I/O 统计信息grep ‘[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}’ some_file
grep -E “error|failure” some_file
grep ‘[0-9]$’ some_file
退出码(或返回码)表示子进程返回其父进程的码。
0是退出码,表示成功,而大于1的码表示错误。
每个数字都有不同的含义,具体取决于应用程序的开发方式。
我认为这是一篇可以了解更多的好博客:https://shapeshed.com/unix-exit-codes
硬链接是使用相同inode的相同文件。
软链接是使用不同inode的另一个文件的快捷方式。
可以在不同的文件系统之间创建软链接,而硬链接只能在同一文件系统内创建。
你可以通过在命令末尾指定&来实现。至于为什么,因为一些命令/过程会占用大量的时间来完成执行或永远运行
默认信号为SIGTERM(15)。 该信号可以优雅地终止进程,这意味着它可以保存当前状态配置。
SIGTERM - 终止进程的默认信号
SIGHUP - 常用用法是重新加载配置
SIGKILL - 不能捕获或忽略的信号
运行 kill -l
查看所有可用的信号
Running(运行态)
Waiting (等待态))
Stopped(暂停态)
Terminated(终止态)
Zombie(假死态)
strace
做什么的?ind /some_dir -iname *.yml -print0 | xargs -0 -r sed -i “s/1/2/g”
你可以使用命令top
和 free
你可以使用 split
命令就像这样split -l 25 some_file
在 Linux (和 Unix) 前三个描述符是:
这有一篇好的文章关于这个主题的: https://www.computerhope.com/jargon/f/file-descriptor.htm
Linux中的每个文件(和目录)都有一个索引节点,即与文件相关的存储元数据信息的数据结构
,例如文件的大小,所有者,权限等。
/etc/resolv.conf
用来做什么的? 它包含那些内容?A记录将域名指向IP地址,而PTR记录则相反,并将IP地址解析为域名。
ls
发生了什么? 提供一个详细的答案open("/my/file") = 5
read(5, "file content")
系统调用正在读 /my/file
文件 以及 5 是文件描述符数字.
ip a
你看到一个设备叫做 'lo'. 它是什么以及为什么我们需要它?traceroute
命令做什么的? 它是怎么工作的?这有一些方式去做:
任务 – 调用特定的Ansible模块
模块 – Ansible在你自己的主机或远程主机上执行的实际代码单元。 模块按类别(数据库,文件,网络等)编制索引,也称为任务插件。
Play – 在给定主机上执行的一个或多个任务
Playbook – 一个或多个Play。 每个Play可以在相同或不同的主机上执行
角色 – Ansible角色使你可以基于某些功能/服务对资源进行分组,以便可以轻松地重用它们。 在角色中,你具有变量,默认值,文件,模板,处理程序,任务和元数据的目录。 然后,你只需在剧本中指定角色即可使用该角色。
清单文件定义了在其上执行Ansible任务的主机和/或主机组。
一个清单文件的例子
192.168.1.2
192.168.1.3
192.168.1.4
[web_servers]
190.40.2.20
190.40.2.21
190.40.2.22
动态清单文件可跟踪来自一个或多个来源(例如云提供商和CMDB系统)的主机。
应该使用当使用外部源时,尤其是在环境中的主机正在自动启动和关闭,而无需跟踪这些源中的所有更改。
- name: Create a new directory
file:
path: "/tmp/new_directory"
state: directory
---
- name: Print information about my host
hosts: localhost
gather_facts: 'no'
tasks:
- name: Print hostname
debug:
msg: "It's me, {{ ansible_hostname }}"
提供完成的代码后,请始终进行彻底检查。 如果你的回答是“这将失败”,那么你是对的。 我们正在使用一个事实(ansible_hostname),
这是我们正在运行的主机上收集到的信息。 但是在这种情况下,我们禁用了事实收集(gather_facts:no),因此该变量将是未定义的,这将导致失败。
---
- hosts: all
vars:
mario_file: /tmp/mario
package_list:
- 'zlib'
- 'vim'
tasks:
- name: Check for mario file
stat:
path: "{{ mario_file }}"
register: mario_f
- name: Install zlib and vim if mario file exists
become: "yes"
package:
name: "{{ item }}"
state: present
with_items: "{{ package_list }}"
when: mario_f.stat.exists
我是 <HOSTNAME> 我的操作系统是 <OS>
替换
---
- name: Deploy /tmp/system_info file
hosts: all:!controllers
tasks:
- name: Deploy /tmp/system_info
template:
src: system_info.j2
dest: /tmp/system_info
The content of the system_info.j2 template
# {{ ansible_managed }}
I'm {{ ansible_hostname }} and my operating system is {{ ansible_distribution }}
根据可变优先级,将使用哪个?
正确的答案是 ‘toad’。
变量优先级是关于变量在不同位置设置时如何相互覆盖的。 如果你到目前为止还没有体验过,我相信你会在某个时候确定的,这使它成为一个有用的话题。
在我们的问题上下文中,顺序将是额外的var(始终覆盖任何其他变量)-> 主机事实 -> 库存变量 -> 角色默认值(最弱)。
完整的列表可以在上面的链接中找到。 另外,请注意Ansible 1.x和2.x之间存在显着差异。
def cap(self, string):
return string.capitalize()
常见的错误答案是说 Ansible 和 Puppet 是配置管理工具而 Terraform 是置备工具。 尽管从技术上讲是正确的,但这并不意味着 Ansible 和 Puppet 不能
用于配置基础结构。 另外,这根本没有解释为什么应该在 CloudFormation上 使用 Terraform。
Terraform与其他工具相比的优势:
terraform.tfstate
文件用来做什么?它跟踪创建的资源的ID,以便Terraform知道它正在管理什么。
terraform init
terraform plan
terraform validate
terraform apply
terraform init
扫描你的代码以查明你正在使用哪些提供程序并下载它们。
terraform plan
可以让你在实际执行操作之前先查看terraform即将执行的操作。
terraform apply
将提供指定的.tf文件资源。
terraform apply
改变的变量?你用这种方式: variable “my_var” {}
local-exec
and remote-exec
in the context of provisioners?这是成功创建的资源,但在配置期间失败。 Terraform将失败,并将该资源标记为“tainted”。
terraform taint
做了什么?Strimg
Integer
Map
List
terraform output
做了什么?容器和虚拟机之间的主要区别是容器使你可以虚拟化
操作系统上有多个工作负载,而对于VM,则将硬件虚拟化为
在多台计算机上运行各自的操作系统。
在以下情况下,你应该选择虚拟机:
* 你需要运行一个需要操作系统所有资源和功能的应用程序
* 你需要完全隔离和安全
在以下情况下,你应该选择容器:
* 你需要快速启动的轻量级解决方案
* 运行单个应用程序的多个版本或实例
Docker CLI 将你的请求传递给Docker守护程序。
Docker 守护程序从 Docker Hub 下载映像
Docker 守护程序使用下载的映像创建一个新容器
Docker 守护程序将输出从容器重定向到 Docker CLI,后者将其重定向到标准输出
Docker Hub是一个本地 Docker 注册表服务,可让你运行 pull 和 push 命令以从 Docker Hub 安装和部署 Docker映像。
Docker Cloud构建在Docker Hub之上,因此Docker Cloud提供了
与Docker Hub相比,你拥有更多的可选/功能。 一个例子是
群管理,这意味着你可以在Docker Cloud中创建新的群。
1. 这是一种由 Guido Van Rosum 于1991年创建的高级通用编程语言。
2. 语言被解释为CPython(用C语言编写)最常用/维护的实现。
3. 它是强类型的。 类型系统是鸭子类型和渐进式的。
4. Python注重可读性,并使用空格/缩进代替括号{}
5. python 包管理器称为PIP“ pip install packages”,具有超过200.000可用的软件包。
6. Python 附带安装了pip和一个大的标准库,为程序员提供了许多预置的解决方案。
7. 在python中,“一切”都是一个对象。
还有许多其他特性,但这是每个python程序员都应该知道的主要特性。
可变数据类型是:
List
Dictionary
Set
不可变数据类型是:
Numbers (int, float, ...)
String
Bool
Tuple
Frozenset
通常,你可以使用函数hash()来检查对象的可变性,如果它是可哈希的,则是不可变的,尽管由于用户定义的对象可能是可变的且可哈希的,所以它并不总是按预期工作
PEP8是Python的编码约定和样式指南的列表
5 种样式指南:
根据定义,继承是一种机制,其中一个对象充当另一个对象的基础,并保留其所有对象属性。
因此,如果B类继承自A类,那么A类的每个特征也将在B类中提供。A类将是“基类”,B类将是“派生类”。
当你有几个共享相同功能的类时,这很方便。
基本语法:
class Base: pass
class Derived(Base): pass
A more forged example:
class Animal:
def __init__(self):
print("and I'm alive!")
def eat(self, food):
print("ñom ñom ñom", food)
class Human(Animal):
def __init__(self, name):
print('My name is ', name)
super().__init__()
def write_poem(self):
print('Foo bar bar foo foo bar!')
class Dog(Animal):
def __init__(self, name):
print('My name is', name)
super().__init__()
def bark(self):
print('woof woof')
michael = Human('Michael')
michael.eat('Spam')
michael.write_poem()
bruno = Dog('Bruno')
bruno.eat('bone')
bruno.bark()
>>> My name is Michael
>>> and I'm alive!
>>> ñom ñom ñom Spam
>>> Foo bar bar foo foo bar!
>>> My name is Bruno
>>> and I'm alive!
>>> ñom ñom ñom bone
>>> woof woof
调用super()会调用Base方法,因此,调用super().__init__() 就是调用 Animal__init__。
有一个称为 MetaClasses 的更高级的python功能,可帮助程序员直接控制类的创建。
# 请注意,你通常不需要了解编译过程,而只需知道一切都来自哪里
# 并给出完整的答案表明你真正知道你在说什么。
通常,每个编译过程都有两个步骤。
- 分析
- 产生代码.
Analysis can be broken into:
1. 词法分析 (标记源代码)
2. 语法分析 (如果语法正确,请检查标记是否合法,tldr)
for i in 'foo'
^
SyntaxError: invalid syntax
We missed ':'
3. 语义分析 (上下文分析,合法语法仍然会触发错误,你是否尝试过除以0,哈希可变对象或使用未声明的函数?)
1/0
ZeroDivisionError: division by zero
这三个分析步骤负责错误处理。
第二步将负责错误,主要是语法错误,这是最常见的错误。
第三步将负责异常。
如我们所见,异常是语义错误,有许多内置的异常:
ImportError
ValueError
KeyError
FileNotFoundError
IndentationError
IndexError
...
你还可以具有用户定义的异常,这些异常必须直接或间接地从Exception类继承。
常见例子:
class DividedBy2Error(Exception):
def __init__(self, message):
self.message = message
def division(dividend,divisor):
if divisor == 2:
raise DividedBy2Error('I dont want you to divide by 2!')
return dividend / divisor
division(100, 2)
>>> __main__.DividedBy2Error: I dont want you to divide by 2!
最简单的是 str[::-1] 但不是效率最高的.
"经典" 方式:
foo = ''
for char in 'pizza':
foo = char + foo
>> 'azzip'
首先,你询问用户要使用的数字量。 使用while循环,每个循环将amount_of_numbers减1,直到amount_of_numbers变为0。 在while循环中,你想询问用户一个数字,该数字将在每次循环运行时添加一个变量。
def return_sum():
amount_of_numbers = int(input("How many numbers? "))
total_sum = 0
while amount_of_numbers != 0:
num = int(input("Input a number. "))
total_sum += num
amount_of_numbers -= 1
return total_sum
with open('file.txt', 'w') as file:
file.write("My insightful comment")
使用 re 模式
li = [[1, 4], [2, 1], [3, 9], [4, 2], [4, 5]]
sorted(x, key=lambda l: l[1])
[{'name': 'Mario', 'food': ['mushrooms', 'goombas']}, {'name': 'Luigi', 'food': ['mushrooms', 'turtles']}]
获取所有的食物类型,最后输出: {'mushrooms', 'goombas', 'turtles'}brothers_menu = \
[{'name': 'Mario', 'food': ['mushrooms', 'goombas']}, {'name': 'Luigi', 'food': ['mushrooms', 'turtles']}]
# "经典" 方式
def get_food(brothers_menu) -> set:
temp = []
for brother in brothers_menu:
for food in brother['food']:
temp.append(food)
return set(temp)
# 一直先行方式 (Using list comprehension)
set([food for bro in x for food in bro['food']])
最简短的方式是: my_string[::-1]
但是这不是效率最高的.
经典方式是:
def reverse_string(string):
temp = ""
for char in string:
temp = char + temp
return temp
return
返回什么?access
, search
insert
and remove
下面的数据结构:负责抓取存储数据的Prometheus服务器推送网关用于短期作业警报管理负责警报 ;)
git pull
和 git fetch
的区别是什么?简单来说, git pull = git fetch + git merge
当你运行git pull时,它会从远程或中央获取所有更改
存储库,并将其附加到本地存储库中的相应分支。
git fetch从远程存储库获取所有更改,将更改存储在
本地存储库中的单独分支
git 目录
, 工作目录
和 暂存区
Git目录是Git存储项目的元数据和对象数据库的地方。 这是Git最重要的部分,当你从另一台计算机克隆存储库时,它就是复制的。
工作目录是项目一个版本的单个签出。 这些文件将从Git目录中的压缩数据库中拉出,并放置在磁盘上供你使用或修改。
暂存区是一个简单文件,通常包含在你的Git目录中,用于存储有关下一次提交的内容的信息。 有时称为索引,但将其称为暂存区已成为标准。
答案来自 git-scm.com
首先,打开有冲突的文件,然后确定有什么冲突。
接下来,根据你的公司或团队接受的是什么,你可以与自己的
同事解决冲突或自行解决
解决冲突后,使用 git add
git reset
和 git revert
区别是什么?
git revert
创建一个新的提交,撤消上一次提交的更改。
git reset
根据使用情况,可以修改索引或更改分支头当前指向的提交。
使用 git rebase>
命令
git rebase
?提及两个或三个就足够了,最好提到“递归”作为默认值。
recursive
resolve
ours
theirs
这篇文章解释是最好的: https://git-scm.com/docs/merge-strategies
git diff
git checkout HEAD~1 -- /path/of/the/file
也许不错,它是:
有一篇文章关于 Octopus merge: http://www.freblogg.com/2016/12/git-octopus-merge.html
Go 而且有一个很好的社区.
var x int = 2
和 x := 2
区别是什么?结果相同,变量值为2。
with var x int = 2
we are setting the variable type to integer while with x := 2
we are letting Go figure out by itself the type.
错. 我们不能重新声明变量,必须使用声明的变量。
应该根据你的使用情况回答此问题,一些示例是:
func main() {
var x float32 = 13.5
var y int
y = x
}
package main
import "fmt"
func main() {
var x int = 101
var y string
y = string(x)
fmt.Println(y)
}
它看起来在101处设置了什么unicode值,并将其用于将整数转换为字符串。
如果要获取“ 101”,则应使用“ strconv” 软件包,然后替换 y = string(x)
with y = strconv.Itoa(x)
package main
func main() {
var x = 2
var y = 3
const someConst = x + y
}
package main
import "fmt"
const (
x = iota
y = iota
)
const z = iota
func main() {
fmt.Printf("%v\n", x)
fmt.Printf("%v\n", y)
fmt.Printf("%v\n", z)
}
package main
import "fmt"
const (
_ = iota + 3
x
)
func main() {
fmt.Printf("%v\n", x)
}
主要区别在于SQL数据库是结构化的(数据以带有行和列的表格-像是Excel电子表格表格),而NoSQL是
非结构化的,并且数据存储会根据NoSQL DB的设置方式而有所不同,例如
作为键值对,面向文档等
db.books.find({"name": /abc/})
db.books.find().sort({x:1})
#!/bin/bash
取决于所使用的语言和设置,例如在Bash中,默认情况下,脚本将继续运行。
echo $0
echo $?
echo $$
echo $@
echo $#
continue
和 break
. 你什么时候使用它们?😦){ 😐:& };:
使用 if/else 的一种简短方法。 一个例子:
[[ $a = 1 ]] && b=“yes, equal” || b=“nope”
Structured Query Language(结构化查询语言)
主要区别在于SQL数据库是结构化的(数据以
带有行和列的表格-像是Excel电子表格表格),而NoSQL是
非结构化的,并且数据存储会根据NoSQL DB的设置方式而有所不同,例如
作为键值对,面向文档等
ACID代表原子性,一致性,隔离性,耐久性。为了符合ACID,数据库必须满足四个标准中的每个标准
原子性 - 数据库发生更改时,它整体上应该成功或失败。
例如,如果你要更新表,则更新应完全执行。如果仅部分执行,则
更新被视为整体失败,并且不会通过-数据库将恢复为原始状态
更新发生之前的状态。还应该提到的是,原子性确保每个
事务以其自身的独立“单元”完成 - 如果任何部分失败,则整个语句都会失败。
一致性 - 对数据库所做的任何更改都应将其从一种有效状态转变为另一种有效状态。
例如,如果你对数据库进行了更改,则不应破坏它。通过检查和约束来保持一致性
在数据库中预定义。例如,如果你尝试将列的值从字符串更改为int
应该是数据类型字符串,一致的数据库将不允许该事务通过,并且该操作将
不执行
隔离 - 确保数据库不会被“更新中”-因为多个事务正在运行
同时,它仍应保持数据库处于与按顺序运行事务相同的状态。
例如,假设有20个人同时对数据库进行了更改。在
当你执行查询时,已完成20项更改中的15项,但仍有5项正在进行中。你应该
仅看到已完成的15个更改 - 随着更改的进行,你将看不到数据库的更新中。
耐用性 - 更改一旦提交,无论发生什么情况都将保持提交状态
(电源故障,系统崩溃等)。这意味着所有已完成的交易
必须记录在非挥发性内存中。
请注意,SQL本质上符合ACID。某些NoSQL DB可能符合ACID,具体取决于
它们的工作方式,但是根据一般经验,NoSQL DB不被视为符合ACID
SQL - 当数据完整性至关重要时,最适合使用。 由于符合ACID,SQL通常由许多业务实现特别是金融领域。
NoSQL - 非常适合你需要快速扩展的情况。 请记住NoSQL是为Web应用程序设计的
,如果你需要快速将相同信息散布到多台服务器,它将会很好的用
此外,由于 NoSQL 不遵守具有列和行结构的严格表
关系数据库所要求的,你可以将不同的数据类型存储在一起。
笛卡尔积是指第一个表中的所有行都与第二个表中的所有行连接在一起时的结果
表。 这可以通过不定义要联接的键来隐式完成,也可以通过以下方式显式地完成:
在两个表上调用CROSS JOIN,如下所示:
Select * from customers CROSS JOIN orders;
请注意,笛卡尔积也可能是一件坏事 - 执行联接时
在两个都没有唯一键的表上,这可能会导致返回信息
是不正确的。
对于这些问题,我们将使用下面显示的“客户和订单”表:
Customers
Customer_ID | Customer_Name | Items_in_cart | Cash_spent_to_Date |
---|---|---|---|
100204 | John Smith | 0 | 20.00 |
100205 | Jane Smith | 3 | 40.00 |
100206 | Bobby Frank | 1 | 100.20 |
ORDERS
Customer_ID | Order_ID | Item | Price | Date_sold |
---|---|---|---|---|
100206 | A123 | Rubber Ducky | 2.20 | 2019-09-18 |
100206 | A123 | Bubble Bath | 8.00 | 2019-09-18 |
100206 | Q987 | 80-Pack TP | 90.00 | 2019-09-20 |
100205 | Z001 | Cat Food - Tuna Fish | 10.00 | 2019-08-05 |
100205 | Z001 | Cat Food - Chicken | 10.00 | 2019-08-05 |
100205 | Z001 | Cat Food - Beef | 10.00 | 2019-08-05 |
100205 | Z001 | Cat Food - Kitty quesadilla | 10.00 | 2019-08-05 |
100204 | X202 | Coffee | 20.00 | 2019-04-29 |
Select *
From Customers;
Select Items_in_cart
From Customers
Where Customer_Name = “John Smith”;
Select SUM(Cash_spent_to_Date) as SUM_CASH
From Customers;
Select count(1) as Number_of_People_w_items
From Customers
where Items_in_cart > 0;
你可以加入他们的唯一键。 在这种情况下,唯一键为中的Customer_ID
客户表和订单表
Select c.Customer_Name, o.Item
From Customers c
Left Join Orders o
On c.Customer_ID = o.Customer_ID;
with cat_food as (
Select Customer_ID, SUM(Price) as TOTAL_PRICE
From Orders
Where Item like “%Cat Food%”
Group by Customer_ID
)
Select Customer_name, TOTAL_PRICE
From Customers c
Inner JOIN cat_food f
ON c.Customer_ID = f.Customer_ID
where c.Customer_ID in (Select Customer_ID from cat_food);
尽管这是一个简单的声明,但“ with”子句在
在连接到另一个表之前,需要在一个表上运行一个复杂的查询。 用语句很好,
因为你在运行查询时会创建一个伪临时文件,而不是创建一个新表。
目前尚无法获得所有猫粮的总和,因此我们使用了with语句来创建
伪表检索每个客户花费的价格总和,然后正常加入该表。
方案是没有口头回答的问题,需要你满足以下条件之一:
这些问题通常作为应聘者的一项家庭任务作为候选,可以将多个主题结合在一起。
在下面,你可以找到一些场景问题: