2009-07-02 9 views
2

Table commeLINQ Query ou une procédure stockée pour retourner la valeur maximale indiquée dans une colonne

datetime   a1 b1 x2 ... 
07-01-2009 13:10 8 9 10 
07-01-2009 13:11 8 8 2 
07-01-2009 13:12 9 1 1  

1 ligne par seconde pendant une journée entière (= 86400 lignes); ~ 40 colonnes; tous le même format
Je suis à la recherche d'un moyen de récupérer une valeur maximale et l'heure à spécifier par une colonne.

Je suis à la recherche d'un moyen de récupérer une valeur maximale et l'heure à laquelle une colonne doit être spécifiée dans un laps de temps.

Quelque chose comme

Select top 1 time,a1 from table 
    where (datetime>=begin and datetime<end) 
    order by a1 desc 

fonctionne, mais je ne peux pas utiliser la colonne en tant que paramètre.

Une solution LINQ ou un SP serait génial. Dois-je m'inquiéter de la performance lorsque je trie un ensemble de données pour récupérer une valeur maximale? Peut-être que la fonction MAX sera plus rapide.

MISE À JOUR

J'ai essayé de le mettre en œuvre la voie LINQ dynamique, comme Timothy (tvanfossen) a suggéré

Dim q2 = context.table _ 
    .Where("t >= @0 AND t < @1", begin, end) _ 
    .OrderBy("@0 desc", col) _ 
    .Take(1) _ 
    .Select(col) 

mais cela retourne la première valeur de la table. Renvoie la première valeur de la période et non la valeur maximale. En regardant le profileur SQL, je vois qu'il n'y a pas de clause ORDER.
Une idée?

MISE À JOUR 2
Pour une raison quelconque, la valeur de substitution ne fonctionne pas dans la clause orderby.
.OrderBY (col + « desc ») fonctionne

Répondre

1

Si vous voulez que le nom de la colonne pour être dynamique, vous voudrez peut-être utiliser Dynamic Linq du VS2008 code samples. Vous pouvez ensuite spécifier le nom de la colonne à trier.

var query = context.table 
        .Where(t = t.begin <= date && date < t.end) 
        .OrderBy("a1 desc") 
        .Take(1) 
        .SingleOrDefault(); 
2

Dans SQL:

select max(a1) 
from table 
where (datetime>=begin and datetime<end) 

Vous n'avez pas besoin de trier, il suffit d'utiliser la fonction standard globale. Pour pouvoir choisir la colonne de façon dynamique, vous devez créer le SQL dynamiquement, avec une concaténation de chaîne, mais soyez très prudent pour vous assurer que le nom de la colonne est réellement un nom de colonne, et non une injection SQL.

En LINQ, encore une fois il est un agrégat à utiliser:

var res = datacontext.Table 
        .Where(t => t.datetime >= begin && t.datetime < end) 
        .Max(t => t.a1); 

L'expression lambda est passé à Max sélectionner la colonne pour obtenir la valeur maximale. Pour gérer la dynamique colonne sélectionnée, il y a deux voies:

D'abord, vous pouvez construire l'expression en morceaux, bien s'il y a un petit ensemble de colonnes fixes:

Expression<Func<TableType, ColumnType>> colSelector = null; 
switch (column) { 
    case "a1": 
    colSelector = t => t.a1; 
    break; 
    case "b2": 
    colSelector = t => t.b2; 
    break; 
    ... 
} 
var res = datacontext.Table 
        .Where(t => t.datetime >= begin && t.datetime < end) 
        .Max(colSelector); 

Ou, deuxième option: construire la Exprimez-vous avec l'expression API.Voir ici pour plus de détails: http://www.albahari.com/nutshell/predicatebuilder.aspx

0

Je pense que cela fonctionnera. Fondamentalement, utilisez une fonction pour retourner la colonne à l'ordre.

var result = Table 
       .OrderByDescending(row => GetColumnOfInterest(row)) 
       .First() 
       .dateTime; 

int GetColumnOfInterest(Row row) 
{ 
    if (...) 
    { 
     return row.a1; 
    } 
    else if (...) 
    { 
     return row.b1; 
    } 
} 
+0

@ Alex: Je pense que cela signifie l'ordre par doit être traité sur le client, LINQ to SQL ne sera pas en mesure de traduire en SQL. – Richard

+0

@Richard: Bon point, je pense que tu as raison. –

0

Que diriez-vous:

IEnumerable<Table> results = Table; 

switch (condition) 
{ 
    condition 1: 
     results = results.OrderByDescending(row => row.a1); 
    condition 2: 
     results = results.OrderByDescending(row => row.a2); 
    condition 3: 
     results = results.OrderByDescending(row => row.a3); 

    .... 

} 

var result = results.First().dateTime; 
+0

Cela ressemble beaucoup à la réponse de Richard, où il construit un colSelector. –

Questions connexes