惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
Cyber Attacks, Cyber Crime and Cyber Security
N
News and Events Feed by Topic
Schneier on Security
Schneier on Security
Forbes - Security
Forbes - Security
Webroot Blog
Webroot Blog
PCI Perspectives
PCI Perspectives
www.infosecurity-magazine.com
www.infosecurity-magazine.com
A
Arctic Wolf
Google Online Security Blog
Google Online Security Blog
T
Troy Hunt's Blog
T
Tenable Blog
L
Lohrmann on Cybersecurity
C
Cisco Blogs
罗磊的独立博客
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
T
Threat Research - Cisco Blogs
Attack and Defense Labs
Attack and Defense Labs
T
The Exploit Database - CXSecurity.com
有赞技术团队
有赞技术团队
V2EX - 技术
V2EX - 技术
GbyAI
GbyAI
P
Proofpoint News Feed
雷峰网
雷峰网
Cisco Talos Blog
Cisco Talos Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
Cloudbric
Cloudbric
K
Kaspersky official blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
S
Securelist
M
MIT News - Artificial intelligence
H
Heimdal Security Blog
Vercel News
Vercel News
S
SegmentFault 最新的问题
U
Unit 42
Help Net Security
Help Net Security
S
Schneier on Security
人人都是产品经理
人人都是产品经理
爱范儿
爱范儿
Microsoft Azure Blog
Microsoft Azure Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
T
Threatpost
I
Intezer
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
P
Palo Alto Networks Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
博客园 - 三生石上(FineUI控件)
J
Java Code Geeks
宝玉的分享
宝玉的分享
Latest news
Latest news

子虚栈

观草木虫鱼鸟兽 仲春夜行记 溶剂上石机理:高分子的溶解性分析 LP1:窒陬记 皆得其宜? 金属清洗笔记 播客解蔽 卖个破绽 MetaBase笔记 动量 随机的殇 MDX+HEXO初试 乙巳大雪摄影小结 字母雕刻笔记 业余无线电笔记 EP4:有纸化生活 格风吹草木 W山游记 巨人的荷塘 小心王二麻子 Oxygen Pro Mini 使用手册 池塘、鱼以及鱼食 在这个疆场的那个地域的领域之内 前端笔记101 九云坊专用程序学习笔记 热传导(稳态)笔记 2025(乙巳)年终总结:泛泛放逸之徒 浅论书写方式:提示词是书写的最终形式吗? 传热学笔记
mysql子查询
· 2025-11-19 · via 子虚栈

厂内MES系统上线前后,因为开发人员紧缺,作为关键用户之一,也跟着学了一些SQL,开发维护了一些报表。今日遇到一个棘手的连接,在此记录一下。

问题分析

系统中数据库里几个关键的表如下,其中数据收集结果工单工序的出料通过前者的so_router_step_out_id与后者的id进行连接。

  1. 数据收集结果(data_collection_result)
    1. 操作条件(dcr_operation_condition)
    2. 尺寸检验(dcr_operation_condition)
    3. 表面缺陷(dcr_surface_defect)
    4. 过程检验(dcr_process_inspect)
    5. 加工记录(dcr_process_record)
  2. 工单(so)
    1. 工单工序(so_router_step)
      1. 进料(so_router_step_in)
      2. 出料(so_router_step_out)
      3. 退料(so_router_step_rp)
    2. 销售订单行(so_sale_order_item)
    3. 成品要求(so_final_req)

每次工序进行一次生产后,会记录以上数据,现在需要计算一个折合产量的指标,要求如下:

  • 一次产出合宽(WtW_t):根据工单>工单工序>出料(多行)里的宽度(WiW_i)与限重次数(CkC_k)计算:通过不同限重来划分一次产出,计算一次产出下宽度的合宽(∑i=1kWi\sum_{i=1}^k W_i)
  • 连接(ConnectConnect):将合宽返回到出料,作为一个属性加入到出料料行中

相关笔记

经过查阅资料,发现SQL中可以通过子查询(Subquery)来实现类似的需求。子查询就是在正常查询的基础上嵌套一层,从该层里面进行查询。子查询时会先执行内层括号里的语句而后才执行外层的语句。这种方法原则上没有上限,可以无限嵌套🪆,然而套娃层数越多,查询效率越低。

1
2
3
4
5
select a,
from (
select A1
from source
where a > 0) as table


根据子查询返回结果的行数,可以分为两种方式:标量子查询与关联子查询。

标量子查询

顾名思义,这个查询方式的特点就是返回一个唯一的结果,适用于返回诸如平均值、合格率、求和等数据集合的唯一值。因为是返回的唯一值,因而可以用到常数、列名等地方,来进一步的筛选。比如,用子查询查出来平均值,然后用Where语句去筛选出来大于小于平均值的数据,也可以用Group by、Havingf、Oeder by等语句里。

比如这是从14:00至今(19:00),F产线出料的宽度值

1
2
3
4
5
SELECT 
o.width
FROM so_router_step_out o
where o.start_date_time_lt > '2025-11-19 14:00'
GROUP BY o.id
output
1
2
3
4
5
6
7
8
9
10
11
12
633
600
482
612
612
612
612
612
598
482
605
617

取大于平均值的数据,就可以这样操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
SELECT 
o.width
FROM so_router_step_out o
where o.start_date_time_lt > '2025-11-19 14:00'
and
o.width >
(
select
avg(width)
from so_router_step_out
where start_date_time_lt > '2025-11-19 14:00'
)
GROUP BY o.id
output
1
2
3
4
5
6
7
8
9
10
633
600
612
612
612
612
612
598
605
617

关联子查询

标量子查询只能范围唯一的值,如果我们想要返回多个值,比如不同钢种的宽度平均值。就必须用到关联子查询了,还以今天14:00至今(19:20),F产线出料的宽度值以及钢种的信息为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
SELECT 
o.width,
o.steel_grade
FROM so_router_step_out o
where o.start_date_time_lt > '2025-11-19 14:00'
GROUP BY o.id






















各个钢种的平均宽度如下:

平均值计算
1
2
3
4
5
6
7
8
9
10
11
12
13
select
avg(o1.width),
o1.steel_grade
from
so_router_step_out as o1
where
start_date_time_lt > '2025-11-19 14:00'
group by
o1.steel_grade




这是使用标量子查询是会报错的,我们就必须采用关联子查询,与前者不同的是,关联子查询通过一个类似于join语句写法的where语句,将内层与外层的信息连接在一起,比如下例中内外层的steel_grade就是一个连接条件,(注意连接条件一定要写在内层中,写在外层的话作用域就变了,不会起效果。)

关联子查询
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
SELECT 
o.width,
o.steel_grade
FROM so_router_step_out o
where o.start_date_time_lt > '2025-11-19 14:00' and o.width >=
(
select
avg(o1.width)
from
so_router_step_out as o1
where
start_date_time_lt > '2025-11-19 14:00'
and
o1.steel_grade = o.steel_grade
group by
o1.steel_grade
)
GROUP BY o.id













从实际的作用来看,关联子查询与group by的作用是相近的,都是通过一些方法对数据进行了切分。

问题解决

1
2
3
4
5
6
7
8
select
i.id,
o.width as widthtotal
from so_router_step m
left join so_router_step_in i on i.detail_table_id = m.id
left join so_router_step_out o on o.detail_table_id = m.id
where m.resource = '740755479873064960'
group by i.id

通过限重次数(xz_times)与进料id进行分组计算,通内层关联子查询连接合宽,然后借由限重与id两者连接到外层。如果为NULL则返回原有宽度(CASE)实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
SELECT 
i.id AS 进料id,
o.id AS 出料id,
o.sfc AS 出料钢卷号,
o.batch AS 出料批次号,
o.xz_times AS 限重次数,
o.width AS 出料宽度,
CASE
WHEN o.xz_times IS NULL THEN o.width
ELSE (
SELECT SUM(o2.width)
FROM so_router_step_out o2
JOIN so_router_step_in i2 ON i2.detail_table_id = o2.detail_table_id
WHERE i2.id = i.id AND o2.xz_times = o.xz_times
)
END AS 一次产出合宽
FROM so_router_step m
LEFT JOIN so_router_step_in i ON i.detail_table_id = m.id
LEFT JOIN so_router_step_out o ON o.detail_table_id = m.id
WHERE m.resource = '740755479873064960'
GROUP BY o.id
ORDER BY i.id, o.xz_times;

in与exist的区别

  1. IN 的子查询是独立的,无法引用外部表的列
  2. EXISTS可以做关联子查询
  3. 当你需要在子查询中关联外部表时,就应该用 EXISTS 或 JOIN