组合多个查询/查询优化

Posted

技术标签:

【中文标题】组合多个查询/查询优化【英文标题】:combining multiple queries / query optimization 【发布时间】:2022-01-23 23:46:53 【问题描述】:

我制作了一个小示例数据,我分三步修改。我不能做到这一点,也许有一些逻辑的聪明方法?我使用 Microsoft SQL Server

这段代码将生成四个基表,其中包含示例数据和我想要组合的逐步查询,最后的结果应该有 8 个条目:

参考表:

CREATE TABLE ref 
(
    ID int NOT NULL
    NR int NOT NULL
    CONSTRAINT KEYS PRIMARY KEY (ID, NR)
);

INSERT INTO ref
VALUES (1234, 223), (1234, 224), (1234, 225),
       (1235, 123), (1235, 124), (1236, 540),
       (1236, 541), (1237, 233), (1237, 234);

Con1 表:

CREATE TABLE con1 
(
    NR int NOT NULL
    flag int NOT NULL
    PRIMARY KEY (NR)
);

INSERT INTO con1
VALUES (123, 0), (124, 1), (125, 0),
       (220, 0), (222, 0), (223, 0), 
       (224, 0), (225, 1), (300, 0),
       (540, 1), (541, 1);

Con2 表:

CREATE TABLE con2 
(
    NR int NOT NULL
    ID int NOT NULL
    PRIMARY KEY (NR)
);

INSERT INTO con2
VALUES (123, 1235), (124, 1235), (125, 1243),
       (220, 1296), (222, 1255), (223, 1234),
       (224, 1234), (225, 1234), (300, 1267),
       (540, 1236);

信息表:

CREATE TABLE info 
(
    NR int NOT NULL
    SNR int NOT NULL
    SSNR int NOT NULL
    Level int not NULL
    CONSTRAINT KEYS PRIMARY KEY (NR, SNR, SSNR)
);

INSERT INTO info
VALUES (123, 1, 1, 1), (123, 1, 2, 2),
       (123, 1, 3, 2), (123, 2, 1, 1),
       (123, 2, 2, 2), (123, 2, 3, 2),
       (124, 1, 1, 1), (124, 1, 2, 2),
       (124, 1, 3, 2), (125, 1, 1, 1),
       (125, 1, 2, 2), (125, 1, 3, 2),
       (125, 1, 4, 3), (125, 1, 5, 3),
       (220, 1, 1, 1), (220, 1, 2, 2),
       (223, 1, 1, 1), (223, 1, 2, 2),
       (224, 1, 1, 1), (224, 1, 2, 2),
       (224, 1, 3, 2), (225, 1, 1, 1),
       (225, 1, 2, 2), (300, 1, 1, 1),
       (300, 1, 2, 2), (300, 2, 1, 1),
       (300, 2, 2, 2), (540, 1, 1, 1),
       (541, 1, 1, 1);

第 1 步:

SELECT * 
FROM con1
INNER JOIN con2 ON con1.NR = con2.NR
WHERE con1.flag = 1

第 2 步:

SELECT ref.* 
FROM ref
INNER JOIN step1 ON ref.ID = step1.ID

第 3 步:

SELECT * 
FROM step2
INNER JOIN info ON step2.NR = info.NR
WHERE info.Level = 1

我尝试了一些不同的方法,但总是得到太多的结果行

结果应该是这样的:

ID NR Level SNR SSNR
1234 223 1 1 1
1234 224 1 1 1
1234 225 1 1 1
1235 123 1 1 1
1235 123 1 2 1
1235 124 1 1 1
1236 540 1 1 1
1236 541 1 1 1

应该是来自 info 级别=1 的所有条目 排除:

所有在con1和con2交汇处不出现的NR con1 列出的所有带有 flag = 0 的 NR

但包括:

所有排除的 NR 与任何 NR之前排除的 NR 使用相同的 ID(根据 ref)运行

结果与来自 ref 的 NR 匹配 ID 具有相同的列

【问题讨论】:

您是否查看过公用表表达式来保存前两个中间结果? Edit 问题并将您想要的结果与给定的示例数据添加为表格文本。还要添加一个全面的描述产生结果背后的逻辑是什么。 我不知道公用表表达式是什么。它看起来有点像子查询,但在这种情况下使用更好,一般有相关差异吗? 【参考方案1】:

您可以使用Common Table Expressions 轻松做到这一点:

with step1 As (
    Select * 
    From con1
    Inner Join con2 On con1.NR = con2.NR
    Where con1.flag = 1
), step2 As (
    Select ref.* 
    From ref
    Inner Join step1 On ref.ID = step1.ID
)
Select * 
From step2
Inner Join info On step2.NR = info.NR
Where info.Level = 1

【讨论】:

以上是关于组合多个查询/查询优化的主要内容,如果未能解决你的问题,请参考以下文章

SQL多个表联合查询优化的问题

Orcle查询优化改写-----单表查询

优化类似的 MySQL 子查询

oracle 优化之组合索引

DDD/Presenter 模式 VS 用例优化查询

有没有办法组合 mysqli 查询或给它们一个优化序列?