Comment pivoter une base de données MySQL entité-attribut-valeur de schéma
J'ai besoin de concevoir des tableaux qui stocke toutes les métadonnées des fichiers (c'est à dire, nom de fichier, auteur, titre, date de création), et des métadonnées personnalisées (qui a été ajouté aux fichiers par les utilisateurs, par exemple CustUseBy, CustSendBy). Le nombre de champs de métadonnées personnalisés ne peuvent pas être définies à l'avance. En effet, le seul moyen de déterminer quels et combien de balises personnalisées ont été ajoutés sur les fichiers est d'examiner ce qui existe dans les tableaux.
Pour stocker cela, j'ai créé une table de base (avoir tous les métadonnées des fichiers), un Attributes
table (la tenue des attributs supplémentaires facultatifs qui peuvent être définies sur les fichiers) et un FileAttributes
table (qui attribue une valeur à un attribut d'un fichier).
CREAT TABLE FileBase (
id VARCHAR(32) PRIMARY KEY,
name VARCHAR(255) UNIQUE NOT NULL,
title VARCHAR(255),
author VARCHAR(255),
created DATETIME NOT NULL,
) Engine=InnoDB;
CREATE TABLE Attributes (
id VARCHAR(32) PRIMARY KEY,
name VARCHAR(255) NOT NULL,
type VARCHAR(255) NOT NULL
) Engine=InnoDB;
CREATE TABLE FileAttributes (
sNo INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
fileId VARCHAR(32) NOT NULL,
attributeId VARCHAR(32) NOT NULL,
attributeValue VARCHAR(255) NOT NULL,
FOREIGN KEY fileId REFERENCES FileBase (id),
FOREIGN KEY attributeId REFERENCES Attributes (id)
) Engine=InnoDB;
Des données de l'échantillon:
INSERT INTO FileBase
(id, title, author, name, created)
VALUES
('F001', 'Dox', 'vinay', 'story.dox', '2009/01/02 15:04:05'),
('F002', 'Excel', 'Ajay', 'data.xls', '2009/02/03 01:02:03');
INSERT INTO Attributes
(id, name, type)
VALUES
('A001', 'CustomeAttt1', 'Varchar(40)'),
('A002', 'CustomUseDate', 'Datetime');
INSERT INTO FileAttributes
(fileId, attributeId, attributeValue)
VALUES
('F001', 'A001', 'Akash'),
('F001', 'A002', '2009/03/02');
Maintenant, le problème c'est que je veux afficher les données d'une manière comme ceci:
FileId, Title, Author, CustomAttri1, CustomAttr2, ...
F001 Dox vinay Akash 2009/03/02 ...
F002 Excel Ajay
Ce que la requête va générer ce résultat?
- Quel langage de programmation comptez-vous utiliser?
- MYSQL , je suis de la planification pour obtenir le résultat souhaité par Requête MYSQL et ensuite rejoindre ce résultat à d'autres tables et passer le désiré resultto FrontEnd.
- MySQL n'est pas un langage de programmation...
Vous devez vous connecter pour publier un commentaire.
La question mentionne MySQL, et en fait ce SGBD a une fonction spéciale pour ce genre de problème:
GROUP_CONCAT(expr)
. Prendre un coup d'oeil dans le MySQL manuel de référence sur le groupe-par-fonctions. La fonction a été ajoutée en MySQL version 4.1. Vous serez en utilisantGROUP BY FileID
dans la requête.Je ne suis pas vraiment sûr de savoir comment vous voulez regarder. Si vous voulez tous les attributs répertoriés pour chaque élément (même si cela n'est pas), il sera plus difficile. Cependant, c'est ma suggestion sur la façon de le faire:
Cela vous donne tous les attributs dans le même ordre, ce qui pourrait être utile. La sortie sera comme suit:
De cette façon, vous avez seulement besoin d'un seul DB requête, et la sortie est facile à analyser. Si vous souhaitez stocker les attributs réels Datetime etc. dans la base de données, vous devez utiliser SQL dynamique, mais je préfère rester à l'écart de cela et de stocker les valeurs dans varchars.
La forme générale d'une telle requête serait
Donc, vous avez besoin pour créer de façon dynamique à votre requête dans les attributs dont vous avez besoin. En php-ish pseudocode
Si vous êtes à la recherche de quelque chose de plus utilisable (et jumelables) qu'un groupe-concat résultat, essayez cette solution ci-dessous. J'ai créé quelques tables très similaire à votre exemple, à faire de ce sens.
Cela fonctionne quand:
Tableau A (Fichiers)
Tableau B (Attributs)
Tableau C (Files_Attributes)
Traditionnel requête serait tirer de nombreuses lignes redondantes:
Cette coalescence de requête (approche à l'aide de MAX) peut fusionner les lignes:
C'est la norme "des lignes et des colonnes" problème dans SQL.
Il est plus facile à faire en dehors de SQL.
Dans votre application, procédez de la manière suivante:
Définir une classe simple pour contenir le fichier, les attributs de système, et une Collection d'attributs de l'utilisateur. Une liste est un bon choix pour cette collection d'attributs de clients. Appelons cette classe FileDescription.
Exécuter une simple jointure entre le fichier et tous les attributs de clients pour le fichier.
Écrire une boucle pour assembler FileDescriptions du résultat de la requête.
Récupérer la première ligne, créer un FileDescription et de la première à la clientèle de l'attribut.
Alors qu'il y a plus de lignes à récupérer:
J'ai fait des expériences avec les différentes réponses et Methai la réponse a été la plus pratique pour moi. Mon projet actuel, bien qu'il n'utilise pas de Doctrine, MySQL, a fait quelques lâche tables.
Ce qui suit est le résultat de mon expérience avec Methai la solution:
créer une entité tableau
créer un attribut de la table
créer attributevalue table
créer entity_attributevalue table de jointure
remplir table d'entité
remplir la table attributaire
remplir attributevalue table
remplir entity_attributevalue table
Montrant tous les enregistrements
tableau croisé dynamique
Cependant, il existe des solutions pour l'utilisation de lignes que de colonnes, aka transposer les données.
Il impliquer la requête de trucs à faire dans le plus pur SQL, ou vous devrez compter sur certaines fonctionnalités uniquement disponible dans certaines base de données, à l'aide de tableaux croisés dynamiques (ou la Croix tables).
Comme exemple, vous pouvez voir comment le faire ici dans Oracle (11g).
La programmation version sera plus simple à maintenir et à faire et en plus fonctionne avec n'importe quelle base de données.
Réponse partielle car je ne sais pas MySQL (bien). Dans MSSQL je regarde les tableaux croisés dynamiques ou serait de créer une table temporaire dans une procédure stockée. Il peut être un moment difficile ...