在Linq中旋转
我正在使用LINQ转换实体,并希望执行透视 例如,我有一张桌子:在Linq中旋转,linq,sql-server-2008,linq-to-entities,pivot,pivot-table,Linq,Sql Server 2008,Linq To Entities,Pivot,Pivot Table,我正在使用LINQ转换实体,并希望执行透视 例如,我有一张桌子: | data1 | data2 | +-------+-------+ | 1 | A | | 1 | B | | 2 | P | | 2 | Q | | 2 | R | +---------------+ 我想将其转化为以下结果: | data1 | first | second | third | +-------+-------+-------
| data1 | data2 |
+-------+-------+
| 1 | A |
| 1 | B |
| 2 | P |
| 2 | Q |
| 2 | R |
+---------------+
我想将其转化为以下结果:
| data1 | first | second | third |
+-------+-------+--------+-------+
| 1 | A | B | NULL |
| 2 | P | Q | R |
+--------------------------------+
我希望在LINQ中执行此操作,而不需要进行客户端处理
我看到过这些帖子,但它们并没有完全解决上述情况(据我所知)
注意 我尝试了下面的方法,但它抱怨我不能对无序的集合使用Skip(),而且我看不到一种方法来对组的折叠“data2”信息进行排序
from item in MyTable
group item by item.data1 into g
select new
{
data1 = g.Key,
first = g.Skip(0).FirstOrDefault().data2,
second = g.Skip(1).FirstOrDefault().data2,
third = g.Skip(2).FirstOrDefault().data2,
};
嗯,这似乎有效,不过我想知道它有多有效
from item in MyTable
group item by item.data1 into g
select new
{
data1 = g.Key,
first = g.OrderBy(x => x.data2).Skip(0).FirstOrDefault().data2,
second = g.OrderBy(x => x.data2).Skip(1).FirstOrDefault().data2,
third = g.OrderBy(x => x.data2).Skip(2).FirstOrDefault().data2,
};
(从LINQPad)生成的相应SQL为:
我假设
data2
字段中可以有三列以上
如果是这样,则无法执行返回具有可变属性数的匿名类型的查询。您需要为data2
值集返回一个数组或某种类型的列表
我认为这是你可以做的事情:
var query =
from mt in MyTable
group mt.data2 by mt.data1 into gmts
let d2 = gmts.ToArray()
select new
{
data1 = gmts.Key,
data2 = d2,
length = d2.Length,
};
var pending = query.ToArray();
var maxLength = pending.Max(p => p.length);
Func<string[], string[]> extend = xs =>
{
var r = new string[maxLength];
xs.CopyTo(r, 0);
return r;
};
var results =
from p in pending
select new
{
p.data1,
data2 = extend(p.data2),
};
如果返回默认值,
FirstOrDefault().data2
不会抛出NullReferenceException吗?@Bala:有趣的一点。但它似乎确实起了作用。我只是在我描述的表上进行了测试(我制作了一个测试表),事实上,它导致“第三个”为null
。没有引发异常。我把它记在LINQ幕后魔术师的账上。你应该发布另一个关于它的问题:p@jwd-这不是很有效-它调用数据库3 x n+1,其中n是不同的data1
值的数目。您最好在分组之前或之后将数据放入内存,但一定要在执行选择之前。@Enigmativity:为什么您会说它多次命中数据库?我刚刚在LINQPad中尝试了这一点,它只生成了一个(有点复杂的)SQL查询。诚然,我的真实代码比我问题中的示例更复杂,但是这种类型的查询有什么特别的地方让你说它会多次命中数据库吗?我没有尝试过你的代码,但我确实想避免客户端出现ToArray()
。事实上,我只关心固定数量的列,我不需要超级泛型。@jwd-为什么要避免ToArray()
?@jwd-我已经编辑了我的解决方案,以包含一个返回固定列的查询。我要避免ToArray()
,因为这会将所有这些行从数据库拉入内存。我的问题被简化了,但这是一个更大的查询的一部分,而枢轴发生在整个过程中间的某个地方。
var query =
from mt in MyTable
group mt.data2 by mt.data1 into gmts
let d2 = gmts.ToArray()
select new
{
data1 = gmts.Key,
data2 = d2,
length = d2.Length,
};
var pending = query.ToArray();
var maxLength = pending.Max(p => p.length);
Func<string[], string[]> extend = xs =>
{
var r = new string[maxLength];
xs.CopyTo(r, 0);
return r;
};
var results =
from p in pending
select new
{
p.data1,
data2 = extend(p.data2),
};
var results =
from p in pending
let d2s = extend(p.data2)
select new
{
p.data1,
first = d2s[0],
second = d2s[1],
third = d2s[2],
};