Traitement de données dans fichier

Résolu/Fermé
dna.factory Messages postés 25444 Date d'inscription mercredi 18 avril 2007 Statut Modérateur Dernière intervention 26 décembre 2024 - Modifié par dna.factory le 5/02/2016 à 11:06
dubcek Messages postés 18758 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 24 décembre 2024 - 22 févr. 2016 à 16:21
Bonjour,
J'ai une base de donnée, contenant 1 million d'article.
Chacun de ces articles est composé de 50 champs décrivant l'article
(la liste des champs est dans une table à part).

Toutes les infos sur les articles sont donc dans une table champ de 50 millions de champs, sous la forme

 id article  idchamp   valeur
1 1 alpha
1 2 beta
1 3 gamma
...
2 1 delta
2 2 eta
2 3 itoa
...
900 000 1 kappa
...
900 000 50 lambda


Je voudrais le transformer en format
1;1=alpha -2=beta - 3=gamma;
2;1=delta - 2=eta - 3=iota;
900000;1=kappa....50=lambad;


J'ai testé de faires des boucles de requetes base, ce qui est le plus simple (car en plus, tant qu'a faire, je voudrais remplace l'id article par le nom de l'article présent dans une autre table, et les id de champs par le nom des champs...

Sauf que vous imaginez qu'on arrive à faire des millions de requetes, et du coup, ça prends trop de temps (avec la méthode utilisée, ça prends environ une minute par article... j'en aurais donc pour 900 000 minutes... j'ose pas calculer le temps que ça prendrais).

Je me suis donc dis, je vais tenter de le faire en sed (ou awk, mais je sens que c'est plus du travail pour sed).

Je vais donc chercher comment faire (il me semble que j'ai déja vu des situations équivalents ici même), mais si des gens s'ennuient et son intéressés par l'exercice.

Comme toujours, c'est de la prod, l'important c'est que ça marche, pas que ce soit 'joli'.
Par contre, y'a un catch sur la vitesse de traitement vu la quantité de donnée.

Mis en jeu pour la meilleure réponse : une bière ou un coca sur Paris (je paye juste la boisson, hein, vous vous démerdez pour l'hébergement et le transport) :)




Stop failing the turing test !
A voir également:

6 réponses

dubcek Messages postés 18758 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 24 décembre 2024 5 623
10 févr. 2016 à 09:00
$ awk -f f9.awk fichier
10;1=OFF - 2=NORM - 3=C - 4=3601029829114 - 5=29114 - 6=-9114 - 7=KNOWN - 8=PILES TECHPLUS R6 8+4GRAT 1PCE - 9=2.75 - 10=a - 11=2.75 - 12=aX - 13=0 - 14=1.000000 - 15=1.0 - 16=Prix unitaire - 17= - 18=;
$
$ cat f9.awk
BEGIN { FS=" *[|] *"}
/[0-9]/ {sub("^ *", ""); sub(" *$", ""); c1=$1; c2=$2; $1=$2=""; t[c1]=t[c1] "|" c2 "|" $3}
END {
for (n in t) {
printf n ";"; x=split(t[n], a)
for (k=2; k<=x; k+=2)
printf("%s=%s%s", a[k], a[k+1], k==x-1? c=";\n": c=" - ")
}
}
1
dna.factory Messages postés 25444 Date d'inscription mercredi 18 avril 2007 Statut Modérateur Dernière intervention 26 décembre 2024 1 613
22 févr. 2016 à 09:55
Ca a l'air de faire ce que je veux...
Maintenant, il ne reste plus qu'a espérer que ce que je voulais était bien ce que je voulais (je me comprends... la plupart du temps).
0
dubcek Messages postés 18758 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 24 décembre 2024 5 623
22 févr. 2016 à 11:26
la ligne
/[0-9]/ {sub("^ *", ""); sub(" *$", ""); c1=$1; c2=$2; $1=$2=""; t[c1]=t[c1] "|" c2 "|" $3}

peut être simplifiée par
/[0-9]/ {gsub("^ *| *$", ""); t[$1]=t[$1] "|" $2 "|" $3}
0
dna.factory Messages postés 25444 Date d'inscription mercredi 18 avril 2007 Statut Modérateur Dernière intervention 26 décembre 2024 1 613
Modifié par dna.factory le 22/02/2016 à 15:37
je reve ou :
gsub("^ *| *$", "")

correspond au :
function ltrim(s) { sub(/^[ \t\r\n]+/, "", s); return s };function rtrim(s) { sub(/[ \t\r\n]+$/, "", s); return s };function trim(s) { return rtrim(ltrim(s)); } {print trim($0)}

que j'utilise (trouvé à la va vite sur le net)...

Je suppose que la version que j'utilise est plus puissante mais je sais pas pourquoi, j'aime ben la version courte...
0
dubcek Messages postés 18758 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 24 décembre 2024 5 623
22 févr. 2016 à 16:21
le gsub n'enlève que les espace de début et fin de $0, donc de la ligne entière
0
dubcek Messages postés 18758 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 24 décembre 2024 5 623
Modifié par dubcek le 5/02/2016 à 16:38
hello
comme ça ?
$ cat  fichier
id article idchamp valeur
1 1 alpha
1 2 beta
1 3 gamma
...
2 1 delta
2 2 eta
2 3 itoa
...
900 000 1 kappa
900 000 5 tarpé
900 000 50 lambda
$
$ awk -F '[ ][ ]+' '/[0-9]/ {e="="; m=" - "; printf $1 ";" $2 e $3 m; getline; printf $2 e $3 m; getline; printf $2 e $3 ";\n"}' fichier
1;1=alpha - 2=beta - 3=gamma;
2;1=delta - 2=eta - 3=itoa;
900 000;1=kappa - 5=tarpé - 50=lambda;
0
dna.factory Messages postés 25444 Date d'inscription mercredi 18 avril 2007 Statut Modérateur Dernière intervention 26 décembre 2024 1 613
5 févr. 2016 à 16:49
y'a l'air d'avoir quelque chose, mais je pense que ça va être un peu plus compliqué.
il n'y a pas que 3 champs pour chaque article, il y en dans le cas présent 50
(dans d'autre cas nécessitant la fonction, il y en aura 100+).
Je suppose qu'une boucle pourra résoudre ce problème.

Donc je suppose que dans le awk, il faut inscrire $1 dans une variable, et rajouter un while/if qui checke $1 avec cette variable, et tant que c'est la même chose, on fait getline;printf, si ce n'est plus la même chose, on fait next ?
0
dubcek Messages postés 18758 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 24 décembre 2024 5 623
6 févr. 2016 à 08:09
montre des données plus réalistes
0
dubcek Messages postés 18758 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 24 décembre 2024 5 623
6 févr. 2016 à 12:45
avec un nb.de champs variables
$ cat fichier
id article idchamp valeur
1 1 alpha
1 2 beta
1 3 gamma
...
2 1 delta
2 2 eta
2 3 itoa
2 4 hibou
...
900 000 1 kappa
900 000 5 tarpé
900 000 50 lambda
900 000 100 chou
900 000 500 pou
$
$ awk -f f8.awk fichier | sort
1;1=alpha - 2=beta - 3=gamma;
2;1=delta - 2=eta - 3=itoa - 4=hibou;
900000;1=kappa - 5=tarpé - 50=lambda - 100=chou - 500=pou;
$
$ cat f8.awk
BEGIN { FS="[ ][ ]+"}
/[0-9]/ {sub(" ", "", $1); t[$1]=t[$1] " " $2 " " $3}
END {
for (n in t) {
printf n ";"; x=split(t[n], a, " ")
for (k=1; k<=x; k+=2)
printf("%s=%s%s", a[k], a[k+1], k==x-1? c=";\n": c=" - ")
}
}

0
dna.factory Messages postés 25444 Date d'inscription mercredi 18 avril 2007 Statut Modérateur Dernière intervention 26 décembre 2024 1 613
9 févr. 2016 à 15:56
le sub est inutile, les ids n'ont pas d'espace, c'est une erreur de ma part.
0
zipe31 Messages postés 36402 Date d'inscription dimanche 7 novembre 2010 Statut Contributeur Dernière intervention 27 janvier 2021 6 419
5 févr. 2016 à 17:32
Salut,

Une solution avec sed, mais il ne faut pas qu'il y ait d'espace dans l'ID ;-\

Le fichier de départ :
id article  idchamp   valeur
1 1 alpha
1 2 beta
1 3 gamma
2 1 delta
2 2 eta
2 3 itoa
900000 1 kappa
900000 5 tarpe
900000 50 lambda


Le script sed (script.sed) :
#n
1 n
:z
$ bw
h
N
/^\([^ ;]*\)\( \{2,\}\|;\).*\n\1/ {    
    s/\n[0-9]\+ \{2,\}/ - /
    b z                                
}
x
    s/ \{2,\}/;/1
    s/ \{2,\}/=/g
p
g
D
:w
    s/ \{2,\}/;/1
    s/ \{2,\}/=/g
p


Le résultat :
$ sed -f script.sed plop 
1;1=alpha - 2=beta - 3=gamma
2;1=delta - 2=eta - 3=itoa
900000;1=kappa - 5=tarpe - 50=lambda

0
ryko1820 Messages postés 1677 Date d'inscription dimanche 28 avril 2013 Statut Membre Dernière intervention 15 août 2021 276
7 févr. 2016 à 19:13
Hello,

en SQL c'est plus ou moins un PIVOT. C'est quoi comme base ?
0
dna.factory Messages postés 25444 Date d'inscription mercredi 18 avril 2007 Statut Modérateur Dernière intervention 26 décembre 2024 1 613
8 févr. 2016 à 07:50
postgres.
Mais le select seul prends déjà plusieurs minutes, malgré de multiple réindex-vaccum.

Table1- article
id nom

table 2 liste_champs
id nom

table 3 champs
id, id_article, id_champ, valeur

et le résultat souhaité est :
article.nom; liste_champs.nom=champ.valeur,liste_champs.nom=champs.valeur, etc..
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
dna.factory Messages postés 25444 Date d'inscription mercredi 18 avril 2007 Statut Modérateur Dernière intervention 26 décembre 2024 1 613
8 févr. 2016 à 07:50
je testerai tout ça mardi
0
dna.factory Messages postés 25444 Date d'inscription mercredi 18 avril 2007 Statut Modérateur Dernière intervention 26 décembre 2024 1 613
9 févr. 2016 à 16:24
Encore une fois, vous me donnez exactement ce que je demande.
encore une fois, évidement, je ne demande pas ce que je veux (mais bon, c'est classique dans le milieu).

donc voici exactement les données telles qu'elles sortent de la requete

 article_ref | id_template_champ |                 valeur
-------------+-------------------+-------------------------------------
10 | 1 | OFF
10 | 2 | NORM
10 | 3 | C
10 | 4 | 3601029829114
10 | 5 | 29114
10 | 6 | -9114
10 | 7 | KNOWN
10 | 8 | PILES TECHPLUS R6 8+4GRAT 1PCE
10 | 9 | 2.75
10 | 10 | a
10 | 11 | 2.75
10 | 12 | aX
10 | 13 | 0
10 | 14 | 1.000000
10 | 15 | 1.0
10 | 16 | Prix unitaire
10 | 17 |
10 | 18 |


Utiliser les pipes comme séparateur de champ, c'est pas trop compliqué.
Par contre, ce qui devient compliqué, c'est que le champ valeur peut contenir des espaces, et des champs vides

Je travaille déja sur ce que vous m'avez donné, quitte à modifier les données en entrée 'pour arriver à une situation déjà résolue'.
0