SQL - 将查询数据流拆分为 2 个单独的表 [理论优化]

SQL - Split query data stream into 2 separate tables [Theoretical Optimisation]

我正在用 MapBasic(MapInfo 的编程语言)编写一些 SQL 代码 运行。描述问题的最佳方式是举个例子:

我想 select 将 ShipType="Barge" 的所有记录放入名为 Barges 的查询中,我希望将所有剩余记录放入查询 OtherShips。

我可以简单地使用以下 SQL 命令:

select * from ShipsTable where  ShipType = "Barge" into Barges
select * from ShipsTable where  ShipType <> "Barge" into OtherShips

很好,但我不禁觉得这是低效的。 SQL 不会在数据库中搜索两次吗?在第一个查询的处理过程中,它不会找到适合第二个查询的数据行吗?

相反,如果有这样的命令会更快:

select * from ShipsTable where ShipType = "Barge" into Barges ELSE into OtherShips

我的问题是,你能做到吗?是否有符合此规范的命令?

谢谢,

您可以在 SSIS 中通过条件拆分和两个不同的目的地轻松完成此操作。

但在 TSQL 中并非如此。

然而对于 "fun" 一些可能性在下面进行了考察。

您可以创建一个分区视图,但为此您需要满足的要求非常艰巨,执行计划只是将其全部加载到一个假脱机中,然后无论如何使用两个不同的过滤器读取该假脱机两次。

CREATE TABLE Barges
(
Id INT,
ShipType VARCHAR(50) NOT NULL CHECK (ShipType = 'Barge'),
PRIMARY KEY (Id, ShipType)
)

CREATE TABLE OtherShips
(
Id INT,
ShipType VARCHAR(50) NOT NULL CHECK (ShipType <> 'Barge'),
PRIMARY KEY (Id, ShipType)
)

CREATE TABLE ShipsTable
(
ShipType VARCHAR(50) NOT NULL
)

go

CREATE VIEW ShipsView
AS
SELECT *
FROM Barges
UNION ALL
SELECT *
FROM OtherShips

GO

INSERT INTO ShipsView(Id, ShipType)
SELECT ROW_NUMBER() OVER(ORDER BY @@SPID), ShipType
FROM ShipsTable

或者您可以使用 OUTPUT 子句和可组合 DML,但这需要将两组行插入第一个 table,然后清除不需要的行(第二个 table 只会得到正确的行,不需要任何清理)。

CREATE TABLE Barges2
(
ShipType VARCHAR(50) NOT NULL
)

CREATE TABLE OtherShips2
(
ShipType VARCHAR(50) NOT NULL
)

CREATE TABLE ShipsTable2
(
ShipType VARCHAR(50) NOT NULL
)

INSERT INTO Barges2
SELECT *
FROM 
(
INSERT INTO OtherShips2
OUTPUT INSERTED.*
SELECT *
FROM ShipsTable2
) D
WHERE D.ShipType = 'Barge';

DELETE FROM OtherShips2 WHERE ShipType = 'Barge';

MapBasic 确实为您提供了对 MapInfo 的 'Invert Selection' 的访问权限,它将为您提供未从您的第一个查询中选择的任何内容(假设您的第一个查询有 return 个结果)。您可以使用它的菜单 ID(在 Menu.def 中找到)调用它,它是 311,或者如果您在文件顶部包含 menu.def,您可以通过常量 M_QUERY_INVERTSELECT 引用它。

例如。

Select * from ShipsTable where  ShipType = "Barge" into Barges
Run Menu Command 311

Run Menu Command M_QUERY_INVERTSELECT 如果您包含了菜单定义文件。

我相信这会比按照您的示例进行第二次选择给您带来更好的性能,但是您将无法在不进行其他选择的情况下使用别名命名结果 table。这是否值得使用取决于您的用例,对于需要相当长一段时间的大型查询,它可以节省一些处理时间。