2009-12-16 3 views
0

-je utiliser ce qui suit pour la mise en œuvre aléatoire ordonné résultats dans Linq2SQL:requête Randomized linq2sql que Retournons trop lourd SQL

partial class OffertaDataContext 
    { 
     [Function(Name = "NEWID", IsComposable = true)] 
     public Guid Random() 
     { 
      throw new NotImplementedException(); 
     } 
    } 

Dans la requête suivante:

IEnumerable<Enquirys> visibleOnSite = Enquirys.Where(e => 
    e.EnquiryPublished != null && 
    e.Status != 0 && 
    e.Status != 3 && 
    e.Status != 4 && 
    e.Status != 5 
); 

var linq = (
      from e in db.EnquiryAreas 
      from w in db.WorkTypes 
      where 
      e.SeoPriority != 0 && 
      e.HumanId != null && 
      w.SeoPriority != 0 && 
      e.HumanId != null && 
      e.SeoPriority * w.SeoPriority > 20 && 
      visibleOnSite.Any(f => f.WhereId == e.Id && f.WhatId == w.Id) 
      select new 
      { 
       HWhereId = e.Id, 
       WhereDescription = e.DescriptionText, 
       HWhatId = e.Id, 
       WhatDescription = e.DescriptionText 
      } 
     ).OrderBy(e => db.Random()).Take(14); 

J'ai un problème avec le résultat SQL :

SELECT [t3].[Id] AS [HWhereId], [t3].[DescriptionText] AS [WhereDescription], [t3].[Id2] AS [HWhatId], [t3].[DescriptionText2] AS [WhatDescription] 
FROM (
    SELECT TOP (7) [t0].[Id], [t0].[DescriptionText], [t1].[Id] AS [Id2], [t1].[DescriptionText] AS [DescriptionText2] 
    FROM [dbo].[EnquiryAreas] AS [t0], [dbo].[WorkTypes] AS [t1] 
    WHERE ([t0].[SeoPriority] <> 0) AND ([t0].[HumanId] IS NOT NULL) AND ([t1].[SeoPriority] <> 0) AND ([t0].[HumanId] IS NOT NULL) AND (([t0].[SeoPriority] * [t1].[SeoPriority]) > 20) AND (EXISTS(
     SELECT NULL AS [EMPTY] 
     FROM [dbo].[Enquirys] AS [t2] 
     WHERE ([t2].[EnquiryPlace] = ([t0].[Id])) AND ([t2].[EnquiryWorkType] = ([t1].[Id])) AND ([t2].[EnquiryPublished] IS NOT NULL) AND ([t2].[Status] <> 0) AND ([t2].[Status] <> 3) AND ([t2].[Status] <> 4) AND ([t2].[Status] <> 5) 
     )) 
    ORDER BY NEWID() 
    ) AS [t3] 
ORDER BY NEWID() 

Où tout fonctionne bien si je supprime l'intérieur ORDER BY NEWID(). (Avec les deux, la requête prend trop de temps à finir). Est-il possible que je puisse modifier mon Linq2SQL pour n'aboutir qu'à l'ORDER BY NEWID(). Si non, toute autre solution de contournement? D'autres façons de mettre en œuvre au hasard?

+1

Je suggère thtat tout doesn, le travail t très bien lorsque vous retirez l'ordre intérieur par que vous obtiendrez des résultats différents. Chaque fois que vous utilisez un # supérieur dans une sélection, vous devez passer la commande ou les résultats ne seront pas cohérents d'une exécution à l'autre. D'un autre côté, je ne vois aucune raison que ce soit une table dérivée du tout. – HLGEM

Répondre

0

Tout dépend de la façon dont vous voulez vos données au hasard. Si un résultat pseudo-aléatoire est acceptable, vous pouvez utiliser l'option TABLESAMPLE de SELECT, voir Limiting Result Sets by Using TABLESAMPLE. S'il vous plaît lire le lien dans MSDN car il explique certaines des limitations autour de TABLESAMPEL, spécialement lorsqu'il est utilisé en conjonction avec JOINs.

Si un échantillon vraiment aléatoire est nécessaire, il existe des alternatives à ORDER BY NEWID(). Une solution un peu mieux est d'utiliser NEWID() dans la clause WHERE, associée à une ligne scalaire dépendante pour forcer l'évaluation à chaque ligne:

SELECT * FROM ... 
WHERE 0.01 >= CAST(CHECKSUM(NEWID(), ID) & 0x7fffffff AS float) 

Cela ne règle pas la table, mais il fait encore une analyse prety lourde . Lancez la pagination LINQ par-dessus et vous ne serez pas beaucoup mieux que l'ORDER BY.

Si aucune solution n'est acceptable, il est peut-être temps de revoir les exigences, cette fois avec une meilleure compréhension de l'algèbre relationnelle 101. Après une bonne compréhension des concepts de relation, tuple et clé, retour sur l'idée de « relation aléatoire » devrait résoudre votre problème ...