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。这是否值得使用取决于您的用例,对于需要相当长一段时间的大型查询,它可以节省一些处理时间。
我正在用 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。这是否值得使用取决于您的用例,对于需要相当长一段时间的大型查询,它可以节省一些处理时间。