2016-05-06 2 views
2

J'écris un code SQL à exécuter dans MapBasic (le langage de programmation de MapInfo). La meilleure façon de décrire la question est avec un exemple:SQL - flux de données de requête divisé en 2 tableaux distincts [Optimisation théorique]

Je veux sélectionner tous les enregistrements où ShipType = "Barge" dans une requête nommée Barges et je veux que tous les enregistrements restants soient placés dans une requête OtherShips.

je pourrais simplement utiliser les commandes SQL suivantes:

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

C'est bien et tout, mais je ne peux pas empêcher de penser que cela est inefficace. SQL ne cherchera-t-il pas deux fois dans la base de données? Ne trouvera-t-il pas les lignes de données qui correspondent à la 2ème requête pendant le traitement du 1er?

, il serait plus rapide s'il y avait une commande comme lieu:

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

Ma question est, pouvez-vous faire cela? Y at-il une commande qui correspond à cette spécification?

Merci,

Répondre

0

MapBasic ne vous vous accédez à « Inverser la sélection » de MapInfo qui fournissent donnerait tout ce qui n'a pas été sélectionné à partir de votre première requête (en supposant que votre première requête ne renvoie des résultats). Vous pouvez l'appeler en utilisant son ID de menu (trouvé dans Menu.def) qui est 311 ou si vous incluez menu.def en haut du fichier, vous pouvez le référencer à travers la constante M_QUERY_INVERTSELECT.

par ex.

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

ou Run Menu Command M_QUERY_INVERTSELECT si vous avez inclus le fichier de définitions menus.

Je crois que cela vous donnera une meilleure performance que de faire une deuxième sélection selon votre exemple, mais vous ne seriez pas en mesure de nommer alors le tableau des résultats avec un alias sans faire une autre sélection.Cela dépend de votre cas d'utilisation, que cela vaille la peine d'être utilisé ou non, pour une requête volumineuse qui prend beaucoup de temps, elle pourrait économiser du temps de traitement.

+0

Ah, réponse similaire de Uffe sur le groupe MapInfo-L, n'avait pas encore vu. Il semblerait que vous ayez fait quelques tests et que cela vous donne un peu plus de performance. –

+0

Haha merci pour la réponse malgré tout! :) – Sancarn

1

Vous pouvez le faire assez facilement dans SSIS avec une scission conditionnelle et deux destinations différentes.

Mais pas vraiment dans TSQL.

Cependant, pour certaines possibilités « fun » sont examinées ci-dessous.

Vous pouvez créer une vue partitionnée, mais les conditions que vous devez remplir sont assez ardues et le plan d'exécution charge tout simplement dans un spool, puis lit le spool deux fois avec deux filtres différents de toute façon.

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 

enter image description here

Ou vous pouvez utiliser la clause OUTPUT et composable DML mais qui nécessiteraient d'insérer les deux ensembles de lignes dans la première table, puis nettoyer les lignes indésirables après (la deuxième table ne recevrait les lignes correctes et pas besoin de nettoyage).

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'; 

enter image description here

+0

Wow, je ne savais pas que vous pouviez faire l'une ou l'autre de ces choses ...: O Et aussi ces organigrammes sont épiques! : D Puisque j'ai seulement fait SQL dans MapBasic je n'ai jamais vu de telles choses. Merci pour les idées! Idée 2 me semble plus compréhensible au moins: P – Sancarn