2010-11-27 4 views
4

Est-il possible de transmettre une valeur dans la requête dans dbGetQuery à partir du package RMySQL.Ajout d'une valeur dynamique dans RMySQL getQuery

Par exemple, si j'ai un ensemble de valeurs dans un vecteur de caractères:

df <- c('a','b','c') 

Et je veux faire une boucle à travers les valeurs de tirer une valeur spécifique à partir d'une base de données pour chacun.

library(RMySQL)  
res <- dbGetQuery(con, "SELECT max(ID) FROM table WHERE columna='df[2]'") 

Lorsque j'essaie d'ajouter la référence à la valeur, j'obtiens une erreur. Vous vous demandez s'il est possible d'ajouter une valeur à partir d'un objet R dans la requête.

+1

Duplication de [Requête RSQLite avec variable spécifiée par l'utilisateur dans le champ WHERE] (http://stackoverflow.com/q/3449666/271616) –

+0

Joshua, merci d'avoir signalé cela. c'est une excellente réponse aussi. J'avais cherché des solutions RMySQL. – analyticsPierce

+0

la solution est la même, que vous utilisiez RMySQL ou RSQLlite. –

Répondre

4

Une option consiste à manipuler la chaîne SQL dans la boucle. Au moment où vous avez un littéral de chaîne, le 'df[2]' n'est pas interprété par R comme autre chose que des caractères. Il y aura des ambiguïtés dans ma réponse, parce que df dans votre Q n'est manifestement pas une trame de données (c'est un vecteur de caractère!). Quelque chose comme ça fera ce que vous voulez.

magasin la sortie dans un vecteur numérique:

require(RMySQL) 
df <- c('a','b','c') 
out <- numeric(length(df)) 
names(out) <- df 

Maintenant, nous pouvons boucler sur les éléments de df pour exécuter votre requête trois fois. Nous pouvons régler la boucle de deux façons différentes: i) avec i comme un nombre que nous utilisons pour référencer les éléments de df et out, ou ii) avec i que chaque élément de df à son tour (c.-à-a, puis b, ...). Je vais montrer les deux versions ci-dessous.

## Version i 
for(i in seq_along(df)) { 
    SQL <- paste("SELECT max(ID) FROM table WHERE columna='", df[i], "';", sep = "") 
    out[i] <- dbGetQuery(con, SQL) 
    dbDisconnect(con) 
} 

OU:

## Version ii 
for(i in df) { 
    SQL <- paste("SELECT max(ID) FROM table WHERE columna='", i, "';", sep = "") 
    out[i] <- dbGetQuery(con, SQL) 
    dbDisconnect(con) 
} 

que vous utilisez dépendra de goût personnel. La deuxième version (ii) vous oblige à définir des noms sur le vecteur de sortie out qui sont les mêmes que les données à l'intérieur out. Cela dit, en supposant que votre requête SQL réelle est similaire à celle que vous publiez, ne pouvez-vous pas le faire en une seule instruction SQL, en utilisant la clause GROUP BY, pour regrouper les données avant de calculer max(ID)? Faire des choses simples dans la base de données comme celle-ci sera probablement beaucoup plus rapide. Malheureusement, je n'ai pas d'instance MySQL pour jouer avec et mon SQL-fu est actuellement faible, donc je ne peux pas donner un exemple de cela.

+1

@Gavin, du haut de ma tête, je pense que la question que vous mentionnez dans votre dernier paragraphe serait: 'SELECT max (ID), columna FROM table WHERE columna dans ('a', 'b', 'c') GROUP BY columna' –

+2

N'oubliez pas de vous assurer que vous n'avez rien qui puisse casser la syntaxe SQL dans votre variable. Référence XKCD obligatoire: http://xkcd.com/327/ – Spacedman

+0

@Spacedman, Little Bobby Tables ... classique! –

3

Vous pouvez également utiliser la commande sprintf pour résoudre le problème (c'est ce que j'utilise lors de la création d'applications brillantes).

df <- c('a','b','c')

res <- dbGetQuery(con, sprintf("SELECT max(ID) FROM table WHERE columna='%s'"),df())

Quelque chose le long de ces lignes devrait fonctionner.