2010-07-15 9 views
1

J'ai besoin de votre aide pour construire une déclaration SQL Je ne peux pas m'en sortir.sql rejoindre dans rejoindre?

Dans une base de données, j'ai quatre tables - fichiers, dossiers, dossiers_fichiers et liens.

J'ai beaucoup de fichiers. L'un d'entre eux s'appelle "myFile.txt".

J'ai beaucoup de dossiers. "myFile.txt" est dans certains d'entre eux. Le premier dossier dans lequel il apparaît s'appelle "firstFolder".

J'ai de nombreux liens vers de nombreux dossiers. Le premier lien vers "firstFolder" s'appelle "firstLink".

La structure de données pour l'exemple serait:

// files 
Id: 10 
Name: "myFile.txt" 

// folders 
Id: 20 
Name: "firstFolder" 

// folder_files (join table) 
Id: 30 
Folder_Id: 20 (meaning "firstFolder") 
File_Id: 1 (meaning "myFile.txt") 

// links 
Id: 40 
Name: "firstLink" 
Folder_Id: 20 (meaning "firstFolder") 

PREMIERE QUESTION: Comment puis-je obtenir le record de « monFichier.txt » et le nom et l'identifiant de « FirstLink » (premier lien), interroger sur le fichier Id = 10, basé sur l'ID le plus bas du dossier et le lien?

DEUXIÈME QUESTION: Comment puis-je obtenir l'enregistrement de "myFile.txt" ET le nom et l'ID de "firstLink" (le premier lien), interroger tous les fichiers, en fonction de l'ID le plus bas du dossier et le lien ? Autrement dit, comment puis-je obtenir le premier lien vers le premier dossier contenant "myFile.txt"?

résultant dans un dossier qui ressemble à:

Id: 10 
Name: "myFile.txt" 
LinkId: 40 
LinkName: "firstLink" 

Merci!

+0

Par «premier», voulez-vous dire avec l'ID le plus bas? – Wrikken

+2

J'ai ajouté la balise 'most-n-per-group'. Essayez de cliquer sur cette étiquette et vous verrez de nombreux autres cas du problème équivalent, avec des solutions. Essayez de lire certaines d'entre elles, puis revenez et éditez votre question avec ce que vous avez essayé (il est toujours préférable de faire vos devoirs vous-même). Désolé, je devais cannibaliser votre tag 'subselect' car il y a une limite de cinq tags. Mais vous n'avez pas nécessairement besoin d'une sous-sélection pour résoudre ce problème. –

+0

@Wrikken - oui, le plus bas Id. @bill - merci pour l'édition, je suis assez novice à SQL, que je ne vois pas vraiment comment le plus grand-n-par-groupe se rapporte? Je pense que je fais juste des jointures ...? J'ai creusé autour de ce forum et du web pendant une heure avant de poster. – user110218

Répondre

2

Vous devriez essayer de penser à la façon dont vous voulez que votre ensemble de résultats ressemble. SQL est conçu pour décrire les ensembles de résultats. Si vous pouvez écrire un jeu de résultats hypothétique, vous aurez peut-être plus de facilité à écrire du SQL pour rendre ce jeu de résultats.

J'ai eu du mal à comprendre ce que vous cherchiez, mais je suis sûr que c'est un problème assez simple. Je serais en mesure de vous aider plus facilement si vous pouviez décrire vos résultats plus clairement, bien que vous n'ayez plus besoin de mon aide!

Par exemple (aller avec vous schéma d'origine) Q1 & Q2:

files.Id, files.Name, links.Id, links.Name (4 colonnes)

Q1:

SELECT 
    files.Id, files.Name, links.Id, links.Name 
FROM 
    files, links 
INNER JOIN 
    folder_files 
    ON files.Id = folder_files.File_Id 
INNER JOIN 
    links 
    ON links.Id = folder_files.Folder_Id 
WHERE 
    files.Id = 10 
ORDER BY 
    folder_files.File_Id ASC, links.Id ASC 
LIMIT 1;

(JOIN avec table de dossiers non nécessaire)

Q2:

changer à la fois ASC-DESC

+0

Merci - J'ai pensé à cela peu de temps après la publication, mais il ne s'est pas présenté dans mon édition. C'est là maintenant. – user110218

+0

C'est tout! Deux jointures internes! C'est ce qui me manquait. Merci! – user110218

1

Ceci permet de sélectionner tous les liens pour id fichier 10:

select links.id, links.name 
from files 
left join folder_files on files.id = folder_files.file_id 
left join folders on folder_files.folder_id = folders.id 
left join links on links.folder_id = folders.id 
where files.id=10; 

Modifier la clause where, ajouter limite ou quoi que pour d'autres choses que vous voulez. Il devrait être simple de modifier cela.

+0

Désolé, j'ai mal formulé ma question. Je veux obtenir le nom et l'identifiant du lien, ainsi que les données d'enregistrement du fichier. Donc, ils ne sont pas des requêtes séparées. – user110218

0

Je voudrais essayer ceci:

select f.* 
     , l.Id as LinkId 
     , l.Name as LinkName, 
    from Link l 
     inner join Folder_Files ff on ff.Folder_Id = l.Folder_Id 
     inner join Files f on f.Id = ff.File_Id 
    where f.Id = 10 

résultant de:

Id | Name  | LinkId | LinkName 
10 | myFile.txt | 40  | firstLink 

Est-ce que vous voulez?

0

Compte tenu:

  • plusieurs dossiers par fichier
  • plus de liens par dossier
  • prenant le dossier le plus bas identifiant pour le lien et le lien le plus bas id pour le dossier

Avec l'aide de: mysql: group by ID, get highest priority per each ID

La réponse pour TOUS les fichiers dans la table des fichiers (allez pour Joh la solution de nB pour un seul fichier, ce serait plus rapide):

SELECT file_id, file_name, link_id, link_name FROM (
SELECT file_id, file_name, link_id, link_name, 
    @r := CASE WHEN @prev_file_id = file_id 
        THEN @rn + 1 
        ELSE 1 
       END AS r, 
    @prev_file_id := file_id 
FROM (
    SELECT 
     f.id as file_id, f.name as file_name, l.id as link_id, l.name as link_name 
    FROM files f 
    JOIN folder_files ff 
    ON ff.file_id = f.id 
    JOIN links l 
    ON l.folder_id = ff.folder_id 
    ORDER BY ff.folder_id, l.id -- first folder first, first link to first folder second 
) derived1, 
(SELECT @prev_file_id := NULL,@r:=0) vars 
) derived2 
WHERE r = 1;