2009-07-20 8 views
1

J'ai une table qui pourrait avoir des milliers (des millions peut-être?) D'enregistrements. Il s'agit essentiellement d'une table de trace d'audit qui stocke des entrées de journal spéciales. Cela s'appelle "Logs".SÉLECTION d'une fiche et de tous ses enregistrements de détails étrangers associés, dans une seule requête?

Il existe également une table connexe appelée "LogsExtended" qui stocke zéro ou plusieurs enregistrements supplémentaires pour chaque entrée de la table Logs.

Il y a une configuration de relation de clé étrangère, avec suppression cascade etc.

Je fais un SELECT sur la table de journaux pour sélectionner tous les enregistrements qui se sont produits dans un intervalle de temps spécifique, dites « les 30 derniers jours » .

Cependant, je veux en même temps sélectionner en même temps les enregistrements étrangers liés dans la table LogsExtended. Avec l'intention que les résultats de cette requête seront remplis dans un DataSet qui a l'installation DataRelation appropriée.

J'ai essayé d'utiliser diverses clauses JOIN, mais celles-ci ont toutes tendance à entraîner un comportement incorrect - où les entrées des journaux sont répétées pour chaque enregistrement associé dans la table LogsExtended.

Je veux vraiment éviter la solution de secours évidente qui est d'interroger la table des Logs d'abord, puis, pour chaque résultat, exécuter une requête supplémentaire pour obtenir les enregistrements LogsExtended également. Cela me semble très inutile et pourrait entraîner des milliers de requêtes.

Je pense que je fais un peu d'une montagne d'une taupinière, mais je ne peux pas comprendre.

Merci.

Répondre

1

Vous devez utiliser une jointure gauche, sinon il ne sera pas affiché enregistrements à partir de journaux qui n'ont aucun élément int LogExtended. Comme si

DECLARE @StartDate DATETIME, 
     @EndDate DATETIME 

SELECT @StartDate = '01 Jun 2009', 
     @EndDate = '30 Jun 2009' 

SELECT * 
FROM Logs l LEFT JOIN 
     LogsExtended le ON l.LogID = le.LogID 
WHERE l.Date BEYWEEN @StartDate AND @EndDate 

si vous voulez 2 résultat défini, vous devez exécuter la requête comme

DECLARE @StartDate DATETIME, 
     @EndDate DATETIME 

SELECT @StartDate = '01 Jun 2009', 
     @EndDate = '30 Jun 2009' 

SELECT l.* 
FROM Logs l 
WHERE l.Date BEYWEEN @StartDate AND @EndDate 

SELECT le.* 
FROM Logs l INNER JOIN 
     LogsExtended le ON l.LogID = le.LogID 
WHERE l.Date BEYWEEN @StartDate AND @EndDate 

ce retournera tous les journaux entre les dates, tous les journaux étendus pour que les mêmes journaux originaux mis

+0

Cette deuxième solution est très très proche de ce que je veux: ~) Merci pour cela. Ma seule question est ... la base de données MSSQL se rendra-t-elle compte que la clause WHERE a été répétée deux fois? Va-t-il optimiser cela pour qu'il ne le fasse qu'une seule fois? – nbevans

+0

L'utilisation de params comme je l'ai montré devrait aider à optimiser la requête, et placer un index sur la colonne devrait également aider. –

+0

Merci. J'ai décidé d'accepter votre réponse, car elle m'a remis sur la bonne voie. – nbevans

1

L'essence de join dans une relation un-à-plusieurs est de multiplier les lignes de la table "un" autant de fois que la table "plusieurs". Une option que vous pouvez aller avec est de prendre uniquement le LogID de la table des journaux, ainsi que tout le reste des informations de la table LogsExtended:

SELECT L.ID, E.* 
FROM Logs L, LogsExtended E 
WHERE 
L.ID = E.ID 
AND 
(Some date limitation on the Logs table) 
+0

Bien que cela entraîne une duplication des champs de la table «un», c'est probablement la meilleure approche si elle doit être effectuée dans une seule requête/instruction SQL. – CraigTP

+0

Donc, il n'y a aucun moyen de le faire autrement que de retourner beaucoup d'enregistrements en double? Tant que je ne manque pas une astuce ici - alors c'est bien. La question que je suppose maintenant est, quelle est la meilleure façon de transformer ces données "bidimensionnelles à plat" en données 3D dans mon application .NET. En ce moment, j'ai trouvé une solution improvisée qui regroupe les entrées dupliquées dans une seule entrée tout en accumulant les informations "LogsExtended" dans une collection. – nbevans

Questions connexes