2013-10-18 23 views
2

在关闭这个重复之前,请注意,我知道“[c#] [linq] pivot”上有很多问题,我花了整整一天的时间来解决这个问题,现在只有转向SO。如何使用LINQ生成透视数据?

我以这种形式获得的数据,从数据库中:

Item Collection_Period Value 
==== ================= ===== 
Item3  201307   27.2 
Item4  201308   19 
Item3  201209   2.1 
Item2  201307   345 
Item1  201309   13.11 
Item2  201308   34 
Item3  200609   85 
Item4  201308   58.2 
Item3  201209   2.4 
Item2  201309   12.1 
Item1  201209   12.3 

我需要将数据处理成这种格式:

Item CurrMon-3 CurrMon-2 CurrMon-1 
===== ========= ========= ========= 
Item1       13.11 
Item2 345   34   12.1 
Item3 27.2 
Item4 19   58.2 

(只显示最后三个月的数据需要显示)。我想这一点:

var pivoted = new List<PivotedMeanData>(); 
var thisMonth = DateTime.Now.Month; 
var p = meanData 
    .GroupBy(i => i.Description) 
    .Select(g => new PivotedMeanData 
    { 
     Description = g.Key, 
     M3 = g.Where(c => DateTime.ParseExact(c.CollectionPeriod, "yyyyMM", CultureInfo.InvariantCulture).Month == thisMonth - 3).ToString().Select(c => c.Value), 
     M2 = g.Where(c => DateTime.ParseExact(c.CollectionPeriod, "yyyyMM", CultureInfo.InvariantCulture).Month == thisMonth - 2).ToString().Select(c => c.Value), 
     M1 = g.Where(c => DateTime.ParseExact(c.CollectionPeriod, "yyyyMM", CultureInfo.InvariantCulture).Month == thisMonth - 1).ToString().Select(c => c.Value) 
    }); 
return pivoted; 

我有一个类来保存这些数据:

public class PivotedMeanData 
{ 
    public string Description { get; set; } 
    public string M3 { get; set; } 
    public string M2 { get; set; } 
    public string M1 { get; set; } 
} 

MeanData类的定义:

public class MeanData 
{ 
    public string Description { get; set; } 
    public long SeqNo { get; set; } 
    public string CollectionPeriod { get; set; } 
    public long Value { get; set; } 
} 

我搜索了很多,发现this question是完全符合我的挑战。但是,如果我在Where谓词的末尾添加.Select(c => c.Value)(因为我只需要那段时间的值),代码不会编译。

“符”不包含“价值”

所提到的问题是出完全相同的定义(它们只是用来总和,而不是选择)

我在做什么这里错了吗?我的尝试是完全错误还是只是得到了Value是错的?

回答

4

因为你在它枚举字符串中的字符的字符串调用Select()

M3 = g.Where(c => DateTime.ParseExact(c.CollectionPeriod, 
             "yyyyMM", 
             CultureInfo.InvariantCulture) 
          .Month == thisMonth - 3) 
     .ToString()  // string 
     .Select(c => c.Value) //c = char 

我怀疑你想

M3 = g.Where(c => DateTime.ParseExact(c.CollectionPeriod, 
             "yyyyMM", 
             CultureInfo.InvariantCulture) 
          .Month == thisMonth - 3) 
     .Sum(c => c.Value) 
+0

虽然我从拉斐尔的回答中猜到了答案,但我喜欢你的解释。 – Animesh

3

你有没有试过这样做?

g.Where(c => DateTime.ParseExact(c.CollectionPeriod, "yyyyMM", CultureInfo.InvariantCulture).Month == thisMonth - 3).Select(c => c.Value).FirstOrDefault(); 
+0

这对我没有工作,但帮助我达成了答案。我试过'g.Where(predicate).FirstOrDefault().Value.ToString()',它工作。 – Animesh

+0

对不起,当然你必须在firstOrDefault之后指定字段。您是否尝试过在没有ToString()的情况下执行此操作,则不需要进行强制转换。 – Raphael

+0

我的不好,我忘了改变类的定义。 M3,M2和M1实际上是字符串。感谢您指出了这一点。我编辑了这个问题。 – Animesh