2011-06-07 4 views
3

J'ai une requête qui sélectionne une ligne/colonne spécifique d'une grande base de données. Disons que la valeur renvoyée est '53. 'Optimisation MYSQL SELECT (simple)

Je dois obtenir:

1. The row that is 3000 rows above this value. 
2. The row that is 3000 rows below this value. 

Si se révéler seulement 2000 lignes au-dessus de la valeur, alors je dois ajouter la différence sur la deuxième requête.

Ex.

1. Find 3000th value up (turns out that only 2000 values are present) 
2. Find 4000th value down. 

Voici comment je l'ai fait (ce qui est une procédure stockée):

SET @s1 = CONCAT('INSERT INTO List1(STD) SELECT t1.STD FROM ',t1,' AS t1 USE INDEX(STD) WHERE t1.STD < ',inp1,' order by STD DESC limit ', inp2); 

PREPARE stmt FROM @s1; 
EXECUTE stmt; 


SET @lim = inp2+(inp2-(SELECT FOUND_ROWS())); 
SET @s2 = CONCAT('INSERT INTO List1(STD) SELECT t1.STD FROM ',t1,' AS t1 USE INDEX(STD) WHERE t1.STD >=', inp1,' order by STD ASC limit ?'); 

PREPARE stmt FROM @s2; 
EXECUTE stmt USING @lim; 

SET @minSD1 = (SELECT MIN(STD) FROM List1); 
SET @maxSD1 = (SELECT MAX(STD) FROM List1); 

Cela semble terriblement rond-point ... est-il pas de meilleure façon?

De même, est-il vraiment impossible d'utiliser un nom de table de variables dans une procédure stockée sans créer une AUTRE procédure stockée (avec le mot-clé PREPARE)?

+0

Il manque beaucoup de contexte ici, comme la signification de toutes les variables mentionnées mais non définies. Sauf si vous fournissez beaucoup plus d'informations, votre question a très peu de sens. –

+0

Ok - laissez-moi à la place me débarrasser des parties inutiles ... –

+0

@Jim Est-ce que cela a plus de sens maintenant? –

Répondre

1

En SQL, le concept de «3000 lignes au-dessus/en dessous d'un point donné» existe UNIQUEMENT dans le contexte d'un ensemble de résultats ordonné et n'est pas défini dans la base de données. À moins qu'il n'y ait un processus algorithmique, basé sur une clé, pour déterminer ce qui est «n lignes au-dessus/en dessous» d'un point donné, alors vous êtes coincé avec les lignes et le comptage, ce que votre solution semble tenter. Je n'ai pas vérifié qu'il fait ce que vous voulez, mais soit cette approche soit celle basée sur les curseurs et le comptage des lignes est le seul moyen d'y arriver.

+0

Hm, ok. C'est ce que je m'étais dis. Est-ce que l'utilisation de curseurs serait au moins plus efficace en mémoire? Je n'ai pas besoin de stocker n'importe quelle valeur sauf la 3000e. –

+0

Un curseur peut être plus efficace car vous pouvez lire et ignorer des lignes sans les stocker. Ecrire le code le plus simple qui fait ce que vous voulez et ensuite décider si c'est assez rapide. Pas de sens de passer 3 jours à écrire la solution "parfaite" quand une heure vous arrivera quelque chose qui fonctionne et qui est assez rapide (optimisation prématurée considérée comme mal ...) –