23 avril 2012 Utiliser une base de données relationnelle sous R Initiation au langage SQL Raymond Baudoin Conservatoire botanique national du Bassin parisien Département EGB [email protected]Ecole doctorale 227 Sciences de la Nature et de l’Homme Module R : APPLICATIONS
78
Embed
Utiliser une base de données relationnelle sous R …edu.mnhn.fr/pluginfile.php/6293/mod_resource/content/0/...24/04/2012 23 avril 2012 Utiliser une base de données relationnelle
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
24/04/201223 avril 2012
Utiliser une base de données relationnelle sous RInitiation au langage SQL
Raymond BaudoinConservatoire botanique national du Bassin parisienDépartement [email protected]
Ecole doctorale 227Sciences de la Nature et de l’Homme
ModuleR : APPLICATIONS
24/04/2012
Utiliser SQL pour manipuler des données sous
Quand on veut filtrer les données à traiter car : Elles sont trop nombreuses Qu’une partie seulement nous intéresse
Elles sont éclatées dans plusieurs entités (fichiers)
C’est-à-dire chaque fois qu’un read.table() n’est pas totalement satisfaisant *
Pour un utilisateur de R
Pour un utilisateur SQL :Quand on souhaite y appliquer des fonctions de R
(*) permet cependant la restriction du nombre de lignes lues
Librairies utilisées : pour la connexion aux bases de données : RODBC, RSQLite, RMySQL, RPostgreSQL, ROracle, DBI pour accéder aux données des :
Fonctions de base pour lire un fichier texte Si le fichier est sous la forme d'un tableau statistique :
read.table (file = fich , # Nom complet du fichier ou "clipboard" pour le presse papier (copier/coller) sep = ";" , # Séparateur des valeurs, \t pour tabulation, \n : pas de séparateurdec = "," , # Symbole décimalheader = FALSE ,stringsAsFactors = TRUE , # Conversion des chaines en facteurrow.names = 1, # colonne utilisée comme identifiant des lignesskip = 1, nrow = 3 ) # Restriction de lecture, ici saut de la première ligne et 3 lignes lues
Si le fichier est sous une autre forme :scan (file = fich , sep=";", what = "character", skip = 1, nlines = 3)
Pour enregistrer un data.frame au format MS-Excel :write.xls(datal, file="localisation.xls", rowNames = TRUE)
Fonctions pour lire une feuille MS-Excel au format .xls
library (xlsReadWrite)
fich <- file.choose() # chemin complet# [1] "C:\\Mes documents sauvegardés\\Enseignement\\Ecole doctorale mnhn\\Module R compl\\Habitants.xls"Encoding (fich) # "UTF-8"fich <- iconv (fich , from = Encoding (fich), to = "latin1") # changement de code page
read.xls (file = fich, sheet = 1, stringsAsFactors = FALSE)Nom Prénom numéro Adresse Code Ville Téléphone Depuis
1 Lecesve André 9 rue Gay Lussac 92320 CHATILLON 146542856 75982 Larrouy Catherine 10 rue Gay Lussac 92320 CHATILLON 140920841 361613 Larrouy Eric 10 rue Gay Lussac 92320 CHATILLON 140920841 36161
read.xls (file=fich, sheet=1, stringsAsFactors=FALSE, dateTime="isodatetime")Nom Prénom numéro Adresse Code Ville Téléphone Depuis
1 Lecesve André 9 rue Gay Lussac 92320 CHATILLON 146542856 1920-10-192 Larrouy Catherine 10 rue Gay Lussac 92320 CHATILLON 140920841 1999-01-013 Larrouy Eric 10 rue Gay Lussac 92320 CHATILLON 140920841 1999-01-01
24/04/2012
SGBD : Système de gestion de base de donnéesOu DBMS (Database management system)
Un ensemble de services pour :
permettre l'accès aux données de façon simple
autoriser un accès aux informations à de multiples utilisateurs
manipuler les données présentes dans la base (insertion, suppression, modification)
Se décompose en trois sous-systèmes :
un système de gestion de fichiers pour le stockage des informations sur le support physique
un système pour gérer l'ordonnancement des informations
une interface avec l'utilisateur
24/04/2012
Elément de base : la table• Les données sont réparties en tables ou entités• Une table est composée de lignes• Une ligne est un ensemble fixe de champs (attributs)
Exemple : la table PersonnesChaque champ a :
un nom
05/09/2005146428564321BernardAuquier10
05/09/2005636699001321AnneAuquier9
05/09/2005157750048321AnneAuquier8
05/06/1960315MichelMeyer6
01/01/1999140920841210EricLarrouy3
01/01/1999140920841210CatherineLarrouy2
19/10/192014654285629AndréLecesve1
DepuisTéléphoneid_localisationnuméroPrénomNomid
Propriétés d’une table :• pas de nom de colonne dupliqué• ordre des lignes sans signification• ordre des colonnes (champs) sans signification• chaque champ permet la sélection de lignes
INTEGER CHARACTER INTEGER DECIMAL DATE• un type
Avec ces propriétés, une table :
un fichier une feuille xls
24/04/2012
alphanumériques(ou CHARACTER)caractèresTexte255CHAR(ou CHARACTER VARYING)caractères32767VARCHAR(ou NATIONAL CHARACTER)NCHAR
temporels
combiné date tempsDate/Heure8TIMESTAMPdu calendrier grégoriendateDATE
entier longEntier Long 2 147 483 6474INTEGER (ou INT)
numériques
Les types de champs 1/2 Les types normalisés SQL 2
24/04/2012
autres typesou LOGICALOui/NonBOOLEANprécision de deux chiffres.NUMERICMonétaireMONEYou BINARYoctet1BYTESentier à incrément automatiqueNuméroAuto4AUTOINC
longueur indéterminécaractèresMémo () 65 536TEXTstockage dans un format déterminéimageIMAGE
BLOBS
Les types de champs 2/2
Les types non normalisés SQL 2
24/04/2012
SGBDR : Le modèle relationnel
Permet la création de liaisons fixes entre les tables en mettant en relation un ou plusieurs champs.
Objectif du modèle :Pas d’information redondante
La clef primaire d'une table est un attribut ou un groupe d'attributs de cette table dont la valeur permet d'identifier de manière unique une ligne de la table.
Entités
Attributs
Relation
Cardinalité : dénombre le nombre d'éléments de l'entité départ en relation avec un élément de l'entité arrivée.
Relations possibles : 1/1, 1/n, n/1, n/m
Une relation n/m nécessite une table de jointure
24/04/2012
SGBDR : Le modèle relationnel
table de jointure
• 1 nom à n téléphones• 1 téléphone est partagépar m nom
relation n / m
L'attribut id de l'entité xxx= clé primaire de la table xxx
permet la relation avec l'entité yyy via l'attribut id_xxx = clé étrangère de la table yyy
24/04/2012
SQLite : SGBDR portable utilisable sous• moteur de base de données relationnelles accessible par le langage SQL.• implémente en grande partie le standard SQL-92• la base de données (déclarations, tables, index et données) stockée dans un fichier• utilisation sans restriction dans des projets aussi bien open source que propriétaires• multi-plateforme
SQLite est le moteur de base de données le plus distribué au monde, grâce à son utilisation dans de nombreux logiciels grand public comme Firefox, Skype, Google Gears, dans certains produits d'Apple, d'Adobe et de McAfee et dans les librairies standards de nombreux langages comme PHP ou Python. De par son extrême légèreté (moins de 300 ko), elle est également très populaire sur les systèmes embarqués, notamment sur la plupart des smartphones modernes.
http://www.sqlite.org/
http://sqlitebrowser.sourceforge.net/
Une « interface » utilisateur : SQLite Database Browser
La librairie sqldf permet à d'utiliser SQLite
24/04/2012
Serveur de donnéesSGBD (DBMS)
Excelfichier texte
Pourquoi se connecter au SGBD ?Sans connexion
fichier.txt.csv
sélectionexport
copiercoller
A refaire si les données sont modifiées ou si mauvaise sélectionIntroduction d’un fichier intermédiaire l’intégrité des données n’est plus respectée
Avec connexion
Intégrité des données respectéeSélection des données dans R
read.table()read.csv2()
odbcDriverConnect()sqlFetch()sqlQuery()
Serveur de donnéesSGBD (DBMS)
Excelfichier texte
Interface de connexion
24/04/2012
Accès à l'application gérant les données
L’interface doit :
ApplicationServeur de données
SGBD (DBMS)Excel
fichier texteDBI
database interface
ODBCOpen DataBase Connectivity
ODBC : interface spécialiséeL'application doit avoir un pilote ODBC.
Exemple : pilote ODBC SQLite http://www.ch-werner.de/sqliteodbc/sqliteodbc.exe
Identifier l'application DBI Driver
DBI Connexion Etablir la connexion
Renvoyer les données DBI Résultats
Dans ce cas la connexion se fait directement sur le pilote ODBC de l'application
rôle des objets de
Interface de connexion
24/04/2012
Des packages R spécifiques* R ≥ 2.9
ApplicationServeur de données
* Contient à la fois le driver et l'interface (DBI)
RMySQL
RPostgreSQL
ROracle
MySQL
PostgreSQL
Oracle
Package source: RMySQL_0.7-4.tar.gz MacOS X binary: RMySQL_0.7-4.tgz Windows binary: RMySQL_0.7-4.zip
Package source: RPostgreSQL_0.1-6.tar.gz MacOS X binary: Non disponibleWindows binary: RPostgreSQL_0.1-6.zip
Package source: ROracle_0.5-9.tar.gz MacOS X binary: Non disponibleWindows binary: Non disponible
RSQLite SQLitePackage source: RSQLite_0.8-2.tar.gz MacOS X binary: RSQLite_0.8-2.tgz Windows binary: RSQLite_0.8-2.zip
RODBCBases de données ayant
un pilote ODBC : Access, Excel, SQLite...
Package source: RODBC_1.3-1.tar.gz MacOS X binary: RODBC_1.3-1.tgz Windows binary: RODBC_1.3-1.zip
Interface de connexion
24/04/2012
La source de données est identifiée par son DSN = Data Source Name
Applicationswindows SGBD
Client Microsoft
Driver ODBCcorrespondant à
l'application source
DS
NODBC
Microsoft, UNIX, Linux
Couche logiciel qui permet la connexion d’une application windows à une source de données
(format défini par Microsoft)ODBC = Open DataBase Connectivity
Client Oracle Oracle
Machine utilisateur Serveur de données distant
24/04/2012
channel <- odbcDriverConnect ()Connexion à une base de données via ODBC
Configuration du DSNL’accès à la base est décrit dans le dsn associé dansC:\Program Files\Fichiers communs\ODBC\Data Sources
Contrôle de l’accès si activé
La base est sur un serveur distant
La base est dans un répertoire accessible
Configurer un lien ODBC sous Windows
• Démarrer• Panneau de configuration• Outils d’administration• Sources de données (ODBC)
Permet d’identifier la source
Nom de la base à connecter
24/04/2012
1. charger la librairielibrary (RSQLite) library (RODBC)
2. charger le pilotedrv <- dbDriver ("SQLite")
3. ouvrir une connexion sur les donnéescon <- dbConnect (drv, dbname=*...) channel <- odbcDriverConnect()* nom de la base uniquement ou channel <- odbcConnectExcel(…)
channel <- odbcConnectAccess(…)4. voir la structure des données (non obligatoire)
5. charger les données avec tous les champsdbReadTable (con, sqtable) sqlFetch (channel, sqtable,…)
6. charger les données avec un SELECT (sql)res <- dbSendQuery (con, sql) sqlQuery (channel, sql,…)
fetch (res, n = -1)dbGetQuery (channel, sql,…)
7. fermer la connexion : OBLIGATOIRE pour libérer l’accèsdbDisconnect (con) close(channel) ou odbcClose(channel)
odbcCloseAll()8. libérer le pilote : dbUnloadDriver (drv)
via DBIexemple : SGBD sqlite
via ODBCConnexion
Connexion : la démarche
24/04/2012
Exemples de connexionà une base sqlite : "SeminR.db"
library (RSQLite)# Se mettre dans le répertoire de la basesetwd(choose.dir()) db <- "SeminR.db"drv <- dbDriver("SQLite")con <- dbConnect(drv, dbname=db)
d’une table : sqlUpdate ()# modification de la 3ème ligne de dataldatal[3,3:4] = datal[1,3:4]datal <- cbind(rownames(datal),datal)colnames(datal)[1] <- "pk"
sqlUpdate (channel, datal[3,], tablename = "datal", index = "pk")
sqlQuery(channel,"SELECT * FROM datal")pk id Adresse Code Ville
1 1 1 avenue Verdun 92170 VANVES2 2 2 rue Gay Lussac 92320 CHATILLON3 3 3 rue Roissis 92170 VANVES
Travailler avec les tables via ODBC
Ajouter des lignes
Modifier des lignes
24/04/2012
sqlClear (channel, "datal")
d’une table : sqlClear ()
sqlQuery(channel,"SELECT count(*) FROM datal")Expr1000
1 0Mais la structure de la table existe toujourssqlSave(channel,datal,rownames = FALSE, append = TRUE)sqlQuery(channel,"SELECT count(*) FROM datal")Expr1000
1 3
sqlDrop ()sqlDrop (channel,"datal")
Travailler avec les tables via ODBC
Supprimer toutes les lignes
Supprimer une table
24/04/2012
Accès aux données Pas de sélection de colonnes
(dDBI <- dbReadTable(con, sqtable))id Adresse Code Ville
1 1 avenue Verdun 92170 VANVES2 2 rue Gay Lussac 92320 CHATILLON3 3 rue Roissis 92140 CLAMART
str(dDBI)'data.frame': 3 obs. of 4 variables:$ id : int 1 2 3$ Adresse: chr "avenue Verdun" "rue Gay Lussac" "rue Roissis"$ Code : int 92170 92320 92140$ Ville : chr "VANVES" "CHATILLON" "CLAMART"
Accès aux données ExcelCommandes identiques à l'accès à un SGBDR sauf sqlQuery()
sqlSave(channel, data1, tablename = "New", rownames = FALSE) Ecriture des données dans une nouvelle feuille
data.frame des données nom de la feuille TRUE par défaut
Pas d’écrire possible dans une feuille vide existante.
Nouveau nom de feuille obligatoire
Ajouter des données dans une feuillesqlSave(channel,data1,tablename = "New", rownames = FALSE, append = TRUE)
Possible que si la feuille à des données
Obligatoire : fermer la connexion pour accéder au fichier par Excelclose(channel)
Commandes RODBC
24/04/2012
Utilisation du language SQL pour sélectionner :
des colonnes des lignes
d'une ou plusieurs tables
par l'utilisation d'une requête SQL
SQL (Structured Query Language)
24/04/2012
SQL (Structured Query Language)
Caractéristiques Inventé en 1970
Déclaratif c'est-à-dire indépendant du contexte d'exécution
Régi par une norme ANSI/ISO Première normalisation ISO en 1987 SQL 2 correspond à la norme SQL/92 SQL 3 en 1999, actuellement SQL 2003
Portable sur différentes plates-formes aussi bien matérielles que logicielles.
Une commande SQL écrite dans un environnement Windows sous MS-ACCESS est utilisable directement dans un environnement ORACLE sous Unix.
Langage normalisé pour décrire, manipuler, contrôler l'accès et interrogerles bases de données relationnelles
24/04/2012
SQL (Structured Query Language)
Langage de requêtes structuréregroupant :
un langage de contrôle des accès (DCL, Data Control Language)
un langage de définition de données (DDL Data Definition Language)
Pour créer, modifier ou supprimer des tables dans la base
un langage de manipulation de données (DML, Data Manipulation Language)
Pour sélectionner, insérer, modifier ou supprimer des données dans une table
24/04/2012
Les commandes SQL
DCL : Contrôle des donnéesGRANT Attribution de droits d'accès REVOKE Suppression de droits d'accès COMMIT Prise en compte des mises à jour ROLLBACK Suppression des mises à jour
DDL : Description des donnéesCREATE Création de tables ALTER Modification de tables DROP Suppression de tables
DML : Manipulation des donnéesSELECT Interrogation des données
INSERT Insertion de lignes dans une table UPDATE Mise à jour de lignes dans une table DELETE Suppression de lignes dans une table
24/04/2012
SELECT [ALL | DISTINCT] { * | col | expr [AS alias], ... }FROM table [alias], ...[ WHERE { conditions de recherche | sous conditions} ][ GROUP BY col, ...] [HAVING conditions de recherche ][ ORDER BY { col | num } {ASC | DESC}, ...] ;
SELECT Précise les colonnes qui vont apparaître dans la réponse FROM Précise la (ou les) table intervenant dans l'interrogation WHERE Précise les conditions à appliquer sur les lignes avec :
- Des opérateurs de comparaison : =, >, <, >=, <=,<>- Des opérateurs logiques : AND, OR, NOT- Des prédicats : IN, LIKE, NULL, ALL, ANY...
GROUP BY Précise la (ou les) colonne de regroupement HAVING Précise la (ou les) conditions associées à un regroupement ORDER BY Précise l'ordre dans lequel vont apparaître les lignes de la réponse :
dbHasCompleted(res) # test la fin de l’affichage[1] FALSE
fetch(res, n = -1) id Adresse Code Ville
3 3 rue Roissis 92140 CLAMART
dbHasCompleted(res)[1] TRUE
Autres fonctions :dbClearResult (res) # libère le lien à la table. A faire pour un nouveau dbSendQuery() si dbHasCompleted(res)→FALSEdbColumnInfo (res) # à sqlColumns() dbGetStatement (res) # affiche le SELECT
1 1 avenue Verdun 92170 VANVES2 2 rue Gay Lussac 92320 CHATILLON3 3 rue Roissis 92140 CLAMART
Première utilisation
Deuxièmeutilisation
DBI
ODBC
Accès aux données via SQLLa requête :
24/04/2012
sqldf () permet l'usage des requêtes SQL sur : les tables d'une base SQLite des data frames des fichiers textes
Utilise les librairies : • DBI (data base interface)• RSQLite : pilote (driver) R pour l’accès à une base SQLite
library (sqldf) pour l'utilisation d'une base de données sqlite
24/04/2012
Connexion à une base sqlite via sqldf () Ouverture d'une connexion à la base sqlite "nom_de_la_base" *
* exclusivement le nom de la base et non le chemin completsqldf (dbname = "nom_de_la_base")
Si "nom_de_la_base" non trouvé : création d'une base vide à ce nom
Si dbname non précisé : ouverture d'une base virtuelle( sqldf () )<SQLiteConnection:(1036,0)>
Utilisation des commandes DBI :dbGetInfo(SQLite())$num_con # nombre de connexions ouvertescon <- sqldf (dbname = "nom_de_la_base") # récupération de l’identifiant de la connexiondbListTables(con) # liste les tables de la base "SQLite" connectée
Fermeture de la connexion au 2ème appelsqldf () NULL
Exemple d’un script setwd(dirname(dbase <- file.choose())) # change le répertoirede sélection de la dbase = iconv(dbase,Encoding(dbase),"latin1") # conversion code caractèrebase à connecter dbase <- substring(dbase,max(unlist(gregexpr("\\",dbase,fixed=TRUE)))-1)
nom* d'une base SQLitepar défaut :ouvre une base virtuelle en mémoire
nom d'une connexion sur une base SQLiteouverte par :- dbConnect ()- sqldf (dbname = )
par défaut
SELECT
• sur des tables d'une base SQLite (ou MySQL)• sur des fichiers textes• sur des data.frames
* uniquement le nom de la base
Remarque sur l'ouverture / fermeture de la connexion( sqldf() ) # ouverture d’une connexion sur une base virtuelle<SQLiteConnection:(1036,0)> ( sqldf() ) # fermeture de la connexion au 2ème appelNULL
OU
Utiliser SQL pour manipuler des données dans library (sqldf)
SELECT [ALL | DISTINCT] { * | col | expr [AS alias], ... }FROM table [alias], ...[ WHERE { conditions de recherche | sous conditions} ][ GROUP BY col, ...] [HAVING conditions de recherche ][ ORDER BY { col | num } {ASC | DESC}, ...] ;
SELECT Précise les colonnes qui vont apparaître dans la réponse FROM Précise la (ou les) table intervenant dans l'interrogation WHERE Précise les conditions à appliquer sur les lignes avec :
- Des opérateurs de comparaison : =, >, <, >=, <=,<>- Des opérateurs logiques : AND, OR, NOT- Des prédicats : IN, LIKE, NULL, ALL, ANY...
GROUP BY Précise la (ou les) colonne de regroupement HAVING Précise la (ou les) conditions associées à un regroupement ORDER BY Précise l'ordre dans lequel vont apparaître les lignes de la réponse :
sql <- "SELECT * FROM Localisation WHERE Ville LIKE 'c%' AND Code > 92200 ;"id Adresse Code Ville
1 2 rue Gay Lussac 92320 CHATILLON
sql <- "SELECT * FROM Localisation WHERE NOT ville = 'VANVES' ;"# avec sqldf(sql) utilisation possible de !=
id Adresse Code Ville1 2 rue Gay Lussac 92320 CHATILLON2 3 rue Roissis 92140 CLAMART
sql <- "SELECT * FROM Localisation WHERE NOT Code = 92320 ;"# idem avec sql <- "SELECT * FROM Localisation WHERE Code <> 92320 ;"id Adresse Code Ville1 1 avenue Verdun 92170 VANVES2 3 rue Roissis 92140 CLAMART
OR, AND, NOTLier les conditions de recherche
opérateurs logiques OR, AND, NOT
AND
NOT
OR
Exécution de la requête SQL :sqldf (sql)sqlQuery (channel, sql)
24/04/2012
GROUP BY Aggrégation des lignes
sql <- "SELECT Ville, count(*) AS Nb_personnes FROM HabitantsGROUP BY Ville ;"Ville Nb_personnes
1 CHATILLON 52 CLAMART 53 VANVES 3
Critères d'aggrégation : min, max, avg, sum ou une expression
sql <- "SELECT Ville, avg(numéro) AS Moy FROM HabitantsGROUP BY Ville ;"Ville Moy
Permet faire un dénombrement (count) ou le calcul d'une fonction d'aggrégationpour les champs des lignes regroupées.
Nombre d'enregistrements par communeExemples :
Moyenne des numéros par commune
Exécution de la requête SQL :sqldf (sql)sqlQuery (channel, sql)
24/04/2012
GROUP BY Réaliser un tableau de contingence
sql <- "SELECT Nom, sum(Ville = 'CHATILLON') AS CHATILLON,sum(Ville = 'CLAMART') AS CLAMART, sum(Ville = 'VANVES') AS VANVESFROM Habitants GROUP BY Nom, Ville ;"
sel <- sqldf("SELECT Nom, Ville FROM Habitants ;")( tab <- table(sel) ) # class 'table' str(tab)as.data.frame(tab) # Résultat non attendu ! Pourquoi ?
class(tab) <- "matrix"as.data.frame(tab) # C'est mieux
Exécution de la requête SQL :sqldf (sql)sqlQuery (channel, sql)
24/04/2012
HAVING Clause " Where" d'un GROUP BY
Exemple : Qui a plus d'un téléphone dans les villes ayant un CP > 92150 ?
sql <- "SELECT Nom, Prénom, Count(Téléphone) AS NbTéléphoneFROM Habitants WHERE Code > 92150GROUP BY Nom, PrénomHAVING Count (Téléphone) >= 2 ;"
Permet d'introduire une condition dans un GROUP BY
Nom Prénom NbTéléphone1 Berrue Christiane 2
Exécution de la requête SQL :sqldf (sql)sqlQuery (channel, sql)
24/04/2012
Dans la clause WHERE
sql <- "SELECT Nom, Prénom, Ville FROM Localisation, Personnes WHERE Localisation.id = id_localisation ;"
Jointure entre tables 1 - Jointure interne
1.1 - Equi-jointure : relier avec une relation d'égalité des tables par un champ commun
Dans le FROM avec INNER JOIN ... ON
sql <- "SELECT Nom, Prénom, Ville FROM Localisation INNER JOIN Personnes ON Localisation.id = id_localisation ;"
Nom Prénom Ville1 Mahier Ludovic VANVES2 Berrue Christiane VANVES3 Berrue Christiane VANVES4 Lecesve André CHATILLON5 Larrouy Catherine CHATILLON6 Larrouy Eric CHATILLON7 Malher Goerges CHATILLON8 Lipinski Ludovic CHATILLON9 Meyer Michel CLAMART10 Foucher Georges CLAMART11 Auquier Anne CLAMART12 Auquier Anne CLAMART13 Auquier Bernard CLAMART
Exécution de la requête SQL :sqldf (sql)sqlQuery (channel, sql)
24/04/2012
Jointure entre tables 1 - Jointure interne
1.2 - Auto-jointure : jointure d'une table avec elle-même
Exemple : Qui partage le même téléphone ?
sql <- "SELECT a.Nom, a.Prénom, a.Téléphone FROM Habitants a, Habitants bWHERE a.id <> b.id AND a.Téléphone = b.Téléphone;"
Nom Prénom Téléphone1 Larrouy Catherine 1409208412 Larrouy Eric 140920841
Rechercher des champs qui se trouvent à l'intérieur d'une même table.
Utilisation obligatoire d'un alias
Exécution de la requête SQL :sqldf (sql)sqlQuery (channel, sql)
24/04/2012
Jointure entre tables 1 - Jointure interne
1.3 - Théta jointure : jointure avec un opérateur de comparaison autre que =
Exemple : Dans un ordre alphabétique, combien de villes sont après chaque ville ?
sql <- "SELECT a.Ville, COUNT(*) AS Reste FROM Localisation a, Localisation bWHERE a.Ville < b.Ville GROUP BY a.Ville;"
Ville Reste1 CHATILLON 22 CLAMART 1
Utilisation possible de : supérieur (>), inférieur (<), supérieur ou égal (>=), inférieur ou égal (<=), différent (<>).
La liste est-elle complète ?
Exécution de la requête SQL :sqldf (sql)sqlQuery (channel, sql)
24/04/2012
Jointure entre tables
sql <- "SELECT count(*) FROM Localisation, Personnes ;"count(*)1 39
Vérification :sqldf ("SELECT count(*) FROM Personnes;") * sqldf("SELECT count(*) FROM Localisation;")count(*)
1 39
Remarques 1/2
Une jointure sans clause WHERE réalise produit cartésien des tables impliquées
Une jointure sur des champs non uniques
sql <- "SELECT P.Nom, P.Prénom, P.Téléphone FROMPersonnes P, Habitants H WHERE P.Nom= H.Nom AND P.Prénom= H.Prénom;"
Nom Prénom Téléphone1 Lecesve André 1465428562 Larrouy Catherine 1409208413 Larrouy Eric 1409208414 Malher Goerges 1465769865 Lipinski Ludovic 1473523296 Meyer Michel NA7 Foucher Georges 1464495018 Auquier Anne 1577500489 Auquier Anne 15775004810 Auquier Anne 63669900111 Auquier Anne 63669900112 Auquier Bernard 14642856413 Mahier Ludovic 14736126614 Berrue Christiane 14638143415 Berrue Christiane 14638143416 Berrue Christiane 95491235517 Berrue Christiane 954912355
réalise le produit entre ces champs
Comment éliminer ces doublons ?
Exécution de la requête SQL :sqldf (sql)sqlQuery (channel, sql)
24/04/2012
Jointure entre tables
sql <- "SELECT P.Nom, P.Prénom, P.Téléphone FROM Personnes P, Habitants H WHERE P.Nom= H.Nom AND P.Prénom= H.Prénom AND P.Téléphone = H.Téléphone;"
ou
sql <- "SELECT P.Nom, P.Prénom, P.Téléphone FROM Personnes P inner join Habitants HON P.Nom= H.Nom AND P.Prénom= H.Prénom AND P.Téléphone = H.Téléphone;"
Jointure sur des champs contenant des valeurs nulles (NULL)
Nom Prénom Téléphone1 Lecesve André 1465428562 Larrouy Catherine 1409208413 Larrouy Eric 1409208414 Malher Goerges 1465769865 Lipinski Ludovic 1473523296 Foucher Georges 1464495017 Auquier Anne 1577500488 Auquier Anne 6366990019 Auquier Bernard 14642856410 Mahier Ludovic 14736126611 Berrue Christiane 14638143412 Berrue Christiane 954912355
Dans ce cas, il manque un nom car : Meyer Michel n'a pas de téléphone
Exécution de la requête SQL :sqldf (sql)sqlQuery (channel, sql)
Remarques 2/2
24/04/2012
Jointure entre tables 2 – Jointure externe
{ LEFT | (RIGHT } OUTER JOIN : pour inclure tous les enregistrements d'une table et seulement ceux de l'autre table pour lesquels les champs joints sont égaux.
FULL OUTER JOIN : pour inclure les enregistrements pour lesquels les champs joints sont égaux ou ont des valeurs nulles.
Exemple :
Utile quand les champs joints ont des valeurs nulles
Habitants LEFT OUTER JOIN Comm2ON Habitants.Code = Comm2.Code
sql <- "SELECT Habitants.Nom, Habitants.Prénom, Comm2.VilleFROM Habitants LEFT OUTER JOIN Comm2 ON Habitants.Code = Comm2.Code;"
24/04/2012
Jointure entre tables 2 – Jointure externe
LEFT OUTER JOINsql <- "SELECT Personnes.Nom, Personnes.Prénom, Personnes.Téléphone FROM
Personnes LEFT OUTER JOIN Habitants ON Personnes.Nom = Habitants.Nom ANDPersonnes.Prénom = Habitants.Prénom AND Personnes.Téléphone = Habitants.Téléphone ;"
Nom Prénom Téléphone1 Lecesve André 1465428562 Larrouy Catherine 1409208413 Larrouy Eric 1409208414 Malher Goerges 1465769865 Lipinski Ludovic 1473523296 Meyer Michel NA7 Foucher Georges 1464495018 Auquier Anne 1577500489 Auquier Anne 63669900110 Auquier Bernard 14642856411 Mahier Ludovic 14736126612 Berrue Christiane 14638143413 Berrue Christiane 954912355
Résultat identique avec :sql <- "SELECT P.Nom, P.Prénom, P.Téléphone
FROM Personnes P, Habitants H WHERE(P.Nom= H.Nom AND P.Prénom= H.Prénom)AND(P.Téléphone = H.Téléphone OR P.Téléphone is null;"
Remarque : sqldf : RIGHT AND FULL OUTER JOINs are not currently supportedMS Access : FULL OUTER JOIN n'existe pas
RIGHT OUTER JOINsql <- "SELECT Personnes.Nom, Personnes.Prénom, Personnes.Téléphone FROM
Habitants RIGHT OUTER JOIN Personnes ON Personnes.Nom = Habitants.Nom ANDPersonnes.Prénom = Habitants.Prénom AND Personnes.Téléphone = Habitants.Téléphone ;"
Exécution de la requête SQL :sqldf (sql)sqlQuery (channel, sql)
24/04/2012
SELECT imbriqués Permet d'utiliser dans la clause WHERE d'un SELECT le résultat d'un autre SELECT
La sous requête peut retourner un sous ensemble de 0 à n valeurs.
En fonction de la condition de la clause WHERE du SELECT principal, on utilisera pour la liaison entre le champ du SELECT principal et les valeurs renvoyées par la sous requête :
un des opérateurs de comparaison : =, >, <, >=, <=,<> un des prédicats : IN, ANY, ALL ou EXISTS
Suivant la condition souhaitée, le prédicat doit être :IN Réalise l'égalité avec un OU entre toutes valeurs ANY Vérifie si au moins une des valeurs satisfait la conditionALL Vérifier si toutes les valeurs satisfont la conditionEXISTS La condition est VRAIE si n valeurs retournées > 0, FAUSSE si n = 0
sql <- "SELECT a.Nom, a.prénom, a.numéro, a.AdresseFROM Habitants aWHERE a.numéro <= (SELECT avg(b.numéro) FROM Habitants b
GROUP BY Adresse HAVING b.Adresse = a.Adresse) ;"
Corrélation
Nom Prénom numéro Adresse1 Lecesve André 9 rue Gay Lussac2 Larrouy Catherine 10 rue Gay Lussac3 Larrouy Eric 10 rue Gay Lussac4 Meyer Michel 15 rue Roissis5 Foucher Georges 17 rue Roissis6 Mahier Ludovic 3 avenue Verdun
Exemple : Nom des habitants dont l'adresse est dans la première moitié de la rue
SELECT imbriqués
Cas particulier :Quand une condition fait intervenir le même champ de la même table
Utilisation obligatoire d'alias
corrélation
Exécution de la requête SQL :sqldf (sql)sqlQuery (channel, sql)
24/04/2012
IN, EXISTS SELECT imbriqués
sql <- "SELECT Adresse, Ville FROM LocalisationWHERE id IN (SELECT id_localisation FROM Personnes WHERE Téléphone IS NULL ) ;"
Exemples d'utilisation
sql <- "SELECT DISTINCT Nom, Prénom , Depuis FROM PersonnesWHERE Depuis IN ( SELECT Depuis FROM Personnes
WHERE nom = 'Larrouy' AND Prénom ='Eric' )AND NOT (nom = 'Larrouy' AND Prénom ='Eric') ;"
Dans quelle(s) rue(s) des habitants n'ont pas de téléphone ?
# Avec une corrélation et EXISTS
Quel(s) habitant(s) ont la même ancienneté qu'Eric Larrouy ?
IN pour tester l'égalité avec toutes valeurs prises une par une (OU)
sql <- "SELECT DISTINCT Nom, Prénom , Depuis FROM Personnes aWHERE EXISTS ( SELECT * FROM Personnes b
WHERE b.nom = 'Larrouy' AND b.Prénom ='Eric'AND b.Depuis = a.Depuis )
AND NOT (a.nom = 'Larrouy' AND a.Prénom ='Eric') ;"
sql1 <- "SELECT DISTINCT Ville, Code FROM Localisation WHERE Ville LIKE 'c%' "sqldf(sql1)
Ville Code1 CHATILLON 923202 CLAMART 92140
Les requêtes doivent impérativement retourner des lignes de composition identique :même champs à la même position
Pour fusionner les lignes issues de deux requêtes
sql2 <- "SELECT DISTINCT Ville, Code FROM Habitants WHERE NOT Ville LIKE 'c%' ;"sqldf(sql2)
Ville Code1 VANVES 92170
Union des requêtes sql1 et sql2sql <- paste (sql1, "UNION", sql2)sqldf(sql)
Ville Code1 CHATILLON 923202 CLAMART 921403 VANVES 92170
Et avecsql2 <- "SELECT DISTINCT Ville, Code, numéro FROM Habitants WHERE NOT Ville LIKE 'c%'"sqlQuery(channel,sql) # [1] "[RODBC] ERROR: Could not SQLExecDirect" sqldf(sql) # Erreur dans sqliteExecStatement
Faire attention au ;qui doit être absent de la première requête(non obligatoire avec ACCESS)
24/04/2012
INTERSECTSélection des lignes communes aux deux requêtes
Utiliser des requêtes imbriquées Utiliser des jointures ...
S'utilise comme UNION
Si non implémenté dans le SQBDR
sql1 <- "SELECT Ville, Code FROM Localisation"sqldf(sql1)
sql2 <- "SELECT Ville, Code FROM Comm2"sqldf(sql2)
Intersection des requêtes sql1 et sql2sql <- paste(sql1,"INTERSECT",sql2)sqldf (sql)
Ville Code1 VANVES 921702 CHATILLON 923203 CLAMART 92140
Ville Code1 CHATILLON 923202 CLAMART 921403 MALAKOFF 92240
Ville Code1 CHATILLON 923202 CLAMART 92140
sqlQuery(channel,sql) # [1] "[RODBC] ERROR
24/04/2012
INTERSECT
sql <- "SELECT L.Ville, L.Code FROM Localisation L, Comm2 C WHERE L.Ville = C.Ville AND L.Code = C.Code ;"
Si non implémenté dans le SQBDRComment faire ?
En utilisant des jointures
sql <- "SELECT * FROM Comm2 C WHERE EXISTS (SELECT * FROM Localisation L
WHERE L.Ville = C.Ville AND L.Code = C.Code) ;"
De même :
sql <- "SELECT L.Ville, L.Code FROM Localisation L WHERE EXISTS (SELECT * FROM Comm2 C
WHERE L.Ville = C.Ville AND L.Code = C.Code) ;"
Utiliser des requêtes imbriquéesExécution requête :sqldf (sql)sqlQuery (channel, sql)
24/04/2012
EXCEPTSélection des lignes différentes d'une requête par rapport à l'autreS'utilise comme UNION
Utiliser des requêtes imbriquées Utiliser des jointures ...Si non implémenté dans le SQBDR
sqlQuery(channel,sql) # [1] "[RODBC] ERROR
sql1 <- "SELECT Ville, Code FROM Localisation"sqldf(sql1)
sql2 <- "SELECT Ville, Code FROM Comm2"sqldf(sql2)
Lignes de sql1 non dans sql2sql <- paste(sql1,"EXCEPT",sql2)sqldf (sql)
Ville Code1 VANVES 921702 CHATILLON 923203 CLAMART 92140
Ville Code1 CHATILLON 923202 CLAMART 921403 MALAKOFF 92240
Ville Code1 MALAKOFF 92240
Lignes de sql2 non dans sql1sql <- paste(sql2,"EXCEPT",sql1)sqldf (sql)
Ville Code1 VANVES 92170
24/04/2012
EXCEPT
# Communes de Localisation non présentent dans Comm2sql1 <- "SELECT L.Ville, L.Code FROM Localisation L WHERE NOT EXISTS (SELECT * FROM Comm2 C
WHERE L.Ville = C.Ville AND L.Code = C.Code);"Ville Code
1 VANVES 92170
# Communes de Comm2 non présentent dans Localisation sql2 <- "SELECT * FROM Comm2 C WHERE NOT EXISTS (SELECT * FROM Localisation L
WHERE L.Ville = C.Ville AND L.Code = C.Code);"id Ville Code
1 3 MALAKOFF 92240
En utilisant des jointures
En utilisant des requêtes imbriquées
# Communes de Localisation non présentent dans Comm2sql1 <- "SELECT L.Ville, L.Code FROM Localisation L LEFT JOIN Comm2 C
ON L.Ville = C.Ville AND L.Code = C.Code WHERE C.Code IS NULL ;"
Ville Code1 VANVES 92170
# Communes de Comm2 non présentent dans Localisation sql2 <- "SELECT C.Ville, C.Code FROM Comm2 C LEFT JOIN Localisation L
ON L.Ville = C.Ville AND L.Code = C.Code WHERE L.Code IS NULL ;"
DELETE * FROM table [alias] [ WHERE { conditions de recherche | sous conditions} ] ;
Commande DELETE
Légende :{ } : Une des valeurs
séparées par '|' obligatoire.
[ ] : Valeur optionnelle.# Création de la table de travail Personne2Personnes <- sqlQuery(channel,"SELECT * FROM Personnes;")sqlSave(channel, Personnes[,-7],"Personne2",rownames=FALSE) sqlQuery(channel,"SELECT * FROM Personne2;")
pour supprimer des lignes d'une tableSyntaxe
sql <- "DELETE * FROM Personne2 WHERE Téléphone IS NULL"
Exemples
Suppression dans la table Personne2 des lignes où le champ Téléphone est nul
sql <- "DELETE * FROM Personne2 Suppression de toutes les lignes de la table Personne2
Remarque : la définition de la table est conservée# VérificationsqlQuery (channel, "SELECT * FROM Personne2;")
Exécution requête :sqlQuery (channel, sql)
24/04/2012
INSERT INTO table [ (col [, col ] ...)]{ VALUES ( val [, val ] ...) | SELECT }
Commande INSERTpour insérer des lignes dans une table
Syntaxe
Exemple
Insérer dans la table Personne2 le contenu des champs Nom, Prénom, numéro, id_localisation, Téléphone à partir de la table Personnes pour les habitants de Clamart.
Légende :{ } : Une des valeurs
séparées par '|' obligatoire.
[ ] : Valeur optionnelle... : Répétition
sql <- "INSERT INTO Personne2 ( Nom, Prénom, numéro, id_localisation, Téléphone )SELECT DISTINCT P.Nom, P.Prénom, P.numéro, P.id_localisation, P.TéléphoneFROM Localisation L, Personnes P WHERE L.id = P.id_localisation AND L.Ville='CLAMART' ;"
# VérificationsqlQuery (channel, "SELECT * FROM Personne2;") # Que remarque-t-on et pourquoi ?
(afficher Habitants)
Exécution requête :sqlQuery (channel, sql)
24/04/2012
UPDATE table [alias] [ INNER JOIN . ON ]SET { col = expr [, col = expr ] ... | ( col [, col ] ... ) = ( SELECT ) }[ WHERE conditions de recherche ]
Commande UPDATEpour modifier le contenu des champs d'une tableSyntaxe
Exemples
Mettre à jour le champ id de la table Personne2 à partir de la table Personnes.
Légende :{ } : Une des valeurs
séparées par '|' obligatoire.
[ ] : Valeur optionnelle... : Répétition
sql <- "UPDATE Personne2 INNER JOIN Personnes ON (Personne2.Téléphone = Personnes.Téléphone)
AND (Personne2.Prénom = Personnes.Prénom)AND (Personne2.Nom = Personnes.Nom)
SET Personne2.id = Personnes.id ;"
(afficher Habitants)
sql <- "UPDATE Personne2 SET id = '999' WHERE Nom ='Foucher' " Mettre 999 dans le champ id de la table Personne2 pour Foucher
# VérificationsqlQuery (channel, "SELECT * FROM Personne2;")
Exécution requête :sqlQuery (channel, sql)
24/04/2012
CREATE TABLE table ( col datatype [DEFAULT expr] [constraint] [, col datatype [DEFAULT expr] [constraint] ... ] )
sql <- "CREATE TABLE New (col1 varchar(20), col2 integer) ;"
sqlQuery (channel,sql)
# VérificationsqlColumns (channel, "New")[, 3:7]
Créer la table New avec deux colonnes
TABLE_NAME COLUMN_NAME DATA_TYPE TYPE_NAME COLUMN_SIZE1 New col1 12 VARCHAR 202 New col2 4 INTEGER 10
DDL
Exécution requête :sqlQuery (channel, sql)
24/04/2012
DROP TABLE table
Commande DROP TABLEpour supprimer une table
Syntaxe
Exemple
sql <- "DROP TABLE New ;"
sql <- "DROP TABLE Personne2 ;"
# Vérification
sqlTables(channel)$TABLE_NAME[-c(1:6)]
Supprimer les tables New et Personne2
# Lister le nom des tables de la basesqlTables (channel)$TABLE_NAME [-c(1:6)]
DDL
Exécution requête :sqlQuery (channel, sql)
24/04/2012
Exercice
Créer une table "communes" à partir de la table "localisation" avec uniquement les communes CHATILLON et CLAMART et en y ajoutant MALAKOFF (92240).La table commune n'a que les champs "Ville" et "Code".
24/04/2012
Exercice
Créer une table "communes" à partir de la table "localisation" avec uniquement les communes CHATILLON et CLAMART et en y ajoutant MALAKOFF (92240).La table commune n'a que les champs "Ville" et "Code".
# 1 - Création de la table comex à partir d'un SELECTsql <- "SELECT DISTINCT Ville, Code FROM Localisation WHERE Ville LIKE 'c%';"sqlCopy(channel, sql, "comex",rownames="id", addPK=TRUE) # par défaut, dans la basesqlQuery(channel,"SELECT * FROM comex ;") # Vérification
# 2 - Création du data.frame avec la nouvelle commune à ajouternewcom <- as.data.frame(cbind("MALAKOFF","92240"))str(newcom ) # Problèmes : factornewcom [,1] <- as.character(newcom[,1])newcom [,2] <- as.integer(as.character(newcom[,2]))# Obligatoire :colnames(newcom) <- c("Ville","Code") # noms champs de la tablerownames(newcom) <- "3" # bonne valeur de l'index ("id")
# 3 - Ajout du data.frame à la tablesqlSave(channel, newcom ,tablename ="comex",