Bonjour,
Désolé, je n’ai pas très bien compris, où vous souhaiter « requêter » ? Ni à quoi ressemble votre MLD (modèle logique de données). Si vous pouvez donner qq exemples de la structure de vos tables (et notamment des liens de jointure entre vos tables avec vos clés étrangères).
- Est ce que vous voulez écrire une formule Python dans une nouvelle table, qui construise cette jointure ?
- Est ce que vous voulez calculer des agrégats (SUM, MOY, MIN, MAX…) dans une table Grist (GROUP BY) ?
- Est ce que vous voulez construire un custom widget ?
Via formule Python
Dans une formule Python, j’écrirais qq chose comme ci-dessous, pour récuperer les lignes de la table « INDICATEUR » lié (jointure) avec la table « STRUCTURE ». Pour l’exemplen j’ai ajouté l’année et le mois mais cela peut être aussi d’autre clé étrangères (tables liées)
import json
table_source = INDICATEUR
# FK_STRUCTURE est une colonne "Référence" dans la table source (clé étrangère)
rows= table_source.lookupRecords(ANNEE=rec.ANNEE, MOIS=rec.MOIS, STRUCTURE=rec.FK_STRUCTURE)
# JSON output debug
dataset = []
for r in rows:
dataset.append({
"id": r.id,
"year": int(r.ANNEE),
"month": r.MOIS,
"structure_code": str(r.STRUCTURE.CODE),
"value": r.VALEUR
})
return json.dumps(dataset, ensure_ascii=False, indent=2)
Via GRIST API javascript
Selon le volume de donnée, (si il est pas trop important) je ferais qq chose
-
Extraction de toutes les données depuis les tables sources sélectionnés
const desiredTables = [ 'TABLE1', 'TABLE2', 'TABLE3'];
const raw = {};
for (const id of desiredTables) {
raw[id] = await grist.docApi.fetchTable(id);
}
-
Normalisation des jeux de données en lignes pour transformer le format Grist (par colonne). Il est plus agréable d’itérer une collection sous la forme d’un tableau classique d’objets Javascript ([ {col1: val, col2: val}, ... ]).
function _normalizeTable(raw) {
if (!raw) return [];
const rows = [];
for (const col of Object.keys(raw)) {
raw[col].forEach((value, i) => {
if (!rows[i]) rows[i] = {};
rows[i][col] = value;
});
}
return rows;
}
-
Le tout dans une fonction
async function fetchAllData() {
const desiredTables = [ 'TABLE1', 'TABLE2', 'TABLE3'];
const raw = {};
for (const id of desiredTables) {
raw[id] = await grist.docApi.fetchTable(id);
}
return {
table1: _normalizeTable(raw.TABLE1),
table2: _normalizeTable(raw.TABLE2),
table3: _normalizeTable(raw.TABLE3)
};
}
-
Puis enfin on peut faire une jointure des tables selon son besoin (left, full, inner…) en parcourant les items (lignes) de la table.
function leftJoin(leftTable, rightTable, leftKey, rightKey) {
const result = [];
// Itération sur chaque ligne de la table à gauche
for (const leftRow of leftTable) {
let matchFound = false;
// Recherche de correspondance dans la table de droite
for (const rightRow of rightTable) {
// La clé de joinutre pour l'exemple est minimaliste ici, elle peut etre plus complexe
// et dépendre de plus d'items si besoin
if (leftRow[leftKey] === rightRow[rightKey]) {
// Ajout de la fusion des deux lignes dans le dataset final (result)
const mergedRow = { ...leftRow, ...rightRow };
result.push(mergedRow);
matchFound = true;
}
}
// Si aucune correspondance n'a été trouvé, on garde qd même la ligne de gauche (seule)
// conformément au principe de la jointure à gauche
if (matchFound === false) {
result.push(leftRow);
}
}
return result;
}
Attention, ce n’est clairement pas une solution idéale présenté ici. C’est juste pour comprendre. Du poitn de vue de la performance, c’est catastrophique ! Si la table de gauche à 1000 lignes et la table de droite également , la condition de jointure est évalué 1 million de fois. Ce n’est pas avec 10 lignes de codes que l’on remplace un moteur SGBD relationnelle qui sert et qui est optimiser pour ca ^^. Mais il est possible d’optimiser (via un dictionnaire sur la table de droite par exemple, avant de lancer la boucle.
Tout dépend du besoin et contexte