2010-03-05 3 views
3

J'ai un ami qui utilise C# Linq faire rapport sur le tableau suivant:C# LINQ question: Comment identifier et compter les éléments dans un ensemble

varchar(50) name 
datetime when 

Le client veut choisir les colonnes pour résumer, comme Total pour cette année, Total pour l'année dernière, Total pour il y a deux semaines, etc. Chaque colonne aurait une heure de début et de fin résumée avec un décompte. Je l'ai fait une déclaration de sélection rapide pour lui:

select A.name as [Name], 

    (select count(*) from mytable B where A.name = B.name and 
    datepart(yy, when) = datepart(yy,getdate())) as [This Year], 

    (select count(*) from mytable B where A.name = B.name and 
    datepart(yy, when) = (datepart(yy,getdate()) - 1)) as [Last Year] 

from (select distinct name from mytable) A 

J'ai aussi suggéré qu'il fait chaque champ de calcul d'un délégué pour qu'il puisse contenir le désordre de calcul en dehors de la requête. En supposant que chaque délégué aurait une date de début et une date de fin qui ont calculé combien de hits se produisent pour chaque nom distinct, tout le monde veut savoir à quoi ressemblerait le code Linq C#?

+0

Supposons aussi Linq à Sql. ;) –

Répondre

2

Voici une méthode générique qui pourrait être utilisé avec une table et le champ date et renvoie les groupes que vous pouvez compter. Vous devez l'exécuter plusieurs fois pour chaque plage de dates pour laquelle vous souhaitez obtenir des données.

static IQueryable<IGrouping<TKey, TSource>> GroupWithinDates<TSource, TKey>(
    this IQueryable<TSource> source, 
    Expression<Func<TSource, TKey>> keySelector, 
    Expression<Func<TSource, DateTime>> dateSelector, 
    DateTime startDate, 
    DateTime endDate 
) 
{ 
    return source 
     .Where(item => dateSelector(item) >= startDate 
         && dateSelector(item) < endDate) 
     .GroupBy(keySelector) 
} 

// Usage after setting startDate and endDate 
var groups = mytable.GroupWithinDates(
       A => A.name, A => A.when, startDate, endDate) 
// You can then transform to Name and Count 
var groupCounts = groups.Select(g => new {Name = g.Key, Count = g.Count()}; 
5

traduction simple:

DateTime Now = DateTime.Now; 

DateTime thisYearStart = new DateTime(Now.Year, 1, 1); 
DateTime thisYearEnd = thisYearStart.AddYears(1); 
DateTime lastYearStart = thisYearStart.AddYears(-1); 
DateTime lastYearEnd = thisYearStart 

var query = dc.MyTable 
    .GroupBy(a => a.Name) 
    .Select(g => new 
    { 
    Name = g.Key, 
    ThisYearCount = g 
     .Count(b => thisYearStart <= b.When && b.When < thisYearEnd) 
    LastYearCount = g 
     .Count(b => lastYearStart <= b.When && b.When < lastYearEnd) 
    }); 

Soit dit en passant, c'est le sql refondus que je traduisais de:

SELECT A.Name as [Name], 
    SUM(CASE WHEN @start1 <= A.When AND A.When < @end1 THEN 1 ELSE 0 END) as ThisYear, 
    SUM(CASE WHEN @start2 <= A.When AND A.When < @end2 THEN 1 ELSE 0 END) as LastYear 
FROM MyTable A 
GROUP BY A.Name 
Questions connexes