2017-07-11 2 views
1

Comment puis-je adapter la requête ci-dessous afin qu'il ne fonctionne pas inutile UNION ALLà moins la déclaration ci-dessus SELECT il ne trouve pas un match?Abandonner UNION ultérieure toutes les commandes si correspondance trouvée [H2]

SELECT LATITUDE, LONGITUDE FROM coordinates WHERE address = ? AND community = ? 
UNION ALL 
SELECT LATITUDE, LONGITUDE FROM coordinates WHERE address::text = ? AND community::text LIKE ? 
UNION ALL 
SELECT LATITUDE, LONGITUDE FROM coordinates WHERE address::text LIKE ? AND community::text LIKE ? 

Mon tableau coordinates a des colonnes | ID | ADRESSE | VILLE | LATITUDE | J'essaie d'extraire les valeurs de la latitude et de la longitude de la manière la plus efficace, tout en exécutant d'abord les requêtes les plus fortes, c'est-à-dire les instructions SELECT qui retourneront le résultat le plus fiable. Si un résultat est trouvé, renvoyez-le et ignorez les requêtes restantes.

En ce moment j'ai toutes mes requêtes dans un ArrayList que je boucle et exécute individuellement. Si un match() est trouvé, je retourne le resultset. Les requêtes en haut de la liste sont celles qui sont plus strictes, en utilisant = au lieu de LIKE, devenant progressivement moins strictes si aucun résultat n'est trouvé.

Ceci est évidemment inefficace puisque je joue près de 100 requêtes SELECT séparément, donc je l'ai regardé en utilisant UNION ALL et mon plan est de créer une requête géante avec UNION ALL entre chaque déclaration SELECT. Cependant, je suis maintenant confus comment annuler toutes les requêtes ultérieures si une correspondance est trouvée?

approche actuelle:

  queryList.add("SELECT LATITUDE, LONGITUDE FROM coordinates WHERE address = ? AND community = ?"); 
      queryList.add("SELECT LATITUDE, LONGITUDE FROM coordinates WHERE address::text = ? AND community::text LIKE ?"); 
      queryList.add("SELECT LATITUDE, LONGITUDE FROM coordinates WHERE address::text LIKE ? AND community::text LIKE ?")   

      PreparedStatement pStatement = null; 
      ResultSet rs = null; 
      Connection conn = null; 

      for (String currentQuery: queryList) { 
       Connection conn = getConnection(); 
       pStatement = conn.prepareStatement(currentQuery); 
       pStatement.setString(1, "742 Evergreen Terrace"); 
       pStatement.setString(2, "Springfield"); 
       // execute query 
       // if match, break loop and use resultset 
      } 

Donc, avec UNION ALL, comment puis-je avorte si le premier SELECT trouve un match?

EDIT:

J'essaie cette requête, mais elle renvoie tous latitutudes et longitudes au lieu de seulement ceux qui ont amené le match à trouver. Comment puis-je modifier cela pour ne renvoyer que la ligne correspondante?

SELECT LATITUDE, LONGITUDE FROM coordinates 
WHERE EXISTS(SELECT LATITUDE, LONGITUDE FROM coordinates WHERE 
(address = ? AND community = ?) OR WHERE (address::text = ? AND community::text LIKE ?)) 

Répondre

0

Vous devez dactylographier les données. Faites en sorte que le premier sélectionne un enregistrement fictif afin qu'il n'échoue jamais. ou déterminez ce qui n'échouera pas avant de commencer. Vous pouvez ensuite utiliser une sélection imbriquée pour supprimer votre ligne factice. Exemple de syntaxe de base

select Latitude, longitude from 
(
select 'dummy data' as Lattitude, 'AltDummy' as Longitude 
union all 
SELECT LATITUDE, LONGITUDE FROM coordinates WHERE address = ? AND community = ? 
UNION ALL 
SELECT LATITUDE, LONGITUDE FROM coordinates WHERE address::text = ? AND community::text LIKE ? 
UNION ALL 
SELECT LATITUDE, LONGITUDE FROM coordinates WHERE address::text LIKE ? AND community 
) x 
where Lattitude <> 'dummy data' and Longitude <> 'AltDummy' 

Vous aurez également besoin de jeter vos données fictives dans exactement le même type de données que vos données réelles pour que cela fonctionne bien 100% du temps. Soumettez-le au serveur SQL en une seule requête et laissez le serveur SQL faire le travail.

+0

Je ne vois pas comment cela répond à ma question de comment ** annuler les commandes 'UNION ALL' suivantes si une correspondance est trouvée **. Comment créer une ligne fictive (?) Dans ma table provoque l'abandon des commandes 'UNION ALL' suivantes si une correspondance est trouvée dessus? – IanSky

+0

Désolé, je n'ai pas compris ce que vous cherchez.Je pensais que tu avais une erreur. Pour faire ce que vous cherchez, vous avez besoin d'une procédure stockée. Vous ne pouvez pas le faire juste en ligne droite. –

+0

En fait, si vous faites la première sélection dans une table temporaire. Ensuite, vérifiez le nombre de la table temporaire et éventuellement quitter, vous pouvez le faire. Mais les tables temporaires peuvent être lentes avec de grands ensembles de données. –

0

Autre approche:

SELECT LATITUDE, LONGITUDE FROM coordinates 
WHERE (address = ? AND community = ?) 
or (text = ? AND community::text LIKE ?) 
or (text LIKE ? AND community::text LIKE ?) 

résultat net même. Les différences de vitesse varient en fonction de la plate-forme sur laquelle vous travaillez. Mais c'est probablement plus rapide que le précédent.

+0

Merci, j'ai passé les dernières heures à modifier manuellement mon code et c'est plus lent maintenant qu'avant. En effet, l'utilisation de 'OR' n'annule pas les clauses' WHERE 'suivantes si une correspondance est trouvée. Au lieu de cela, votre suggestion signifie que la requête ENTIER doit être exécutée dans son intégralité, avant qu'une correspondance (ou pas) ne soit renvoyée. Peut-être qu'il me manque quelque chose ?? – IanSky

+0

Non, c'est correct. Je ne suivais pas complètement ce qui était demandé. Selon le serveur, vous verrez des résultats plus rapides ou plus lents avec les différentes approches. Essayez l'option de la table temporaire ci-dessus. Cela réduira les lectures, ce que vous semblez chercher. –