是否可以使用 LINQ 进行动态数据透视?

发布于 2024-09-16 02:10:22 字数 1252 浏览 6 评论 0原文

我有一个 T-SQL 2005 查询,它返回:

pid         propertyid  displayname     value
----------- ----------- --------------- ---------------
14270790    74          Low Price       1.3614
14270790    75          High Price      0
14270791    74          Low Price       1.3525
14270791    75          High Price      0
14270792    74          Low Price       1.353
14270792    75          High Price      0
14270793    74          Low Price       1.3625
14270793    75          High Price      0
14270794    74          Low Price       1.3524
14270794    75          High Price      0

我想做的本质上是在 displayname 字段上旋转,希望生成:(

pid       Low Price  High Price
14270790  1.3614     0
14270791  1.3525     0
14270792  1.353      0
14270793  1.3625     0
14270794  1.3524     0

不确定 propertyid 字段将如何输出,所以我留下了它(希望它能简单地位于“低价”和“高价”字段旁边,以指示它们的 ID,但我认为这行不通。)

问题是原始 displayname 的内容字段是动态的 - 它是通过与 PropertyName' 表的联接生成的,因此透视列的数量是可变的,因此它可能包含高价低价,OpenandClose`,具体取决于与该表的连接返回的内容。

当然,这相对容易(不管我在编写初始查询时遇到什么麻烦!) )在固定查询或存储过程中生成此数据透视表但是,是否可以让 LINQ 生成一个 SQL 查询,该查询将命名要生成的每个列,而不必编写动态(可能在存储过程中)查询。列出列名?

谢谢,

马特。

I have a T-SQL 2005 query which returns:

pid         propertyid  displayname     value
----------- ----------- --------------- ---------------
14270790    74          Low Price       1.3614
14270790    75          High Price      0
14270791    74          Low Price       1.3525
14270791    75          High Price      0
14270792    74          Low Price       1.353
14270792    75          High Price      0
14270793    74          Low Price       1.3625
14270793    75          High Price      0
14270794    74          Low Price       1.3524
14270794    75          High Price      0

What I would like to do is essentially pivot on the displayname field, hopefully producing:

pid       Low Price  High Price
14270790  1.3614     0
14270791  1.3525     0
14270792  1.353      0
14270793  1.3625     0
14270794  1.3524     0

(Not sure how the propertyid field would be output, so I left it out (was hoping it would simply sit alongside the Low Price and High Price fields, to indicate their IDs, but I don't think that will work.)

The problem is that the content of the original displayname field is dynamic - it is produced from a join with a PropertyName' table, so the number of pivoted columns is variable. It could therefore containHigh Price,Low Price,OpenandClose`, depending on what the join with that table returns.

It is, of course, relatively easy (regardless of the trouble I'm having writing the initial query!) to produce this pivot in a fixed query or stored proc. However, is it possible to get LINQ to generate a SQL query which would name each column to be produced rather than having to write a dynamic (probably in a stored proc) query which lists out the column names?

Thanks,

Matt.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

望笑 2024-09-23 02:10:22

我会给你一个带有不同数据的样本(我需要的)。您可以根据您的需要进行调整。请注意,仅使用了两个 linq 查询,其他大部分内容是将列表转换为数据表。

         var data = new[] {
                new{Student=1, Subject="English", Marks=40},
                new{Student=1, Subject="Maths", Marks=50},
                new{Student=1, Subject="Science", Marks=60},
                new{Student=1, Subject="Physics", Marks=70},
                new{Student=1, Subject="Chemistry", Marks=80},
                new{Student=1, Subject="Biology", Marks=90},
                new{Student=2, Subject="English", Marks=4},
                new{Student=2, Subject="Maths", Marks=5},
                new{Student=2, Subject="Science", Marks=6},
                new{Student=2, Subject="Physics", Marks=7},
                new{Student=2, Subject="Chemistry", Marks=8},
                new{Student=2, Subject="Biology", Marks=9}
            };

        /*Here the pivot column is the subject and the static column is student
        group the data against the static column(s)*/

        var groups = from d in data
                     group d by d.Student into grp
                     select new
                     {
                         StudentId = grp.Key,
                         Marks = grp.Select(d2 => new { d2.Subject, d2.Marks }).ToArray()
                     };


        /*get all possible subjects into a separate group*/
        var subjects = (from d in data
                        select d.Subject).Distinct();

        DataTable dt = new DataTable();

        /*for static cols*/
        dt.Columns.Add("STUDENT_ID");


        /*for dynamic cols*/
        foreach (var subject in subjects)
        {
            dt.Columns.Add(subject.ToString());
        }

        /*pivot the data into a new datatable*/
        foreach (var g in groups)
        {
            DataRow dr = dt.NewRow();
            dr["STUDENT_ID"] = g.StudentId;

            foreach (var mark in g.Marks)
            {
                dr[mark.Subject] = mark.Marks;
            }
            dt.Rows.Add(dr);
        }   

I'll give you a sample with a different data (that I needed). You can adapt that to your need. Note only two linq queries are used, most of the other fluff is to convert a list into a datatable.

         var data = new[] {
                new{Student=1, Subject="English", Marks=40},
                new{Student=1, Subject="Maths", Marks=50},
                new{Student=1, Subject="Science", Marks=60},
                new{Student=1, Subject="Physics", Marks=70},
                new{Student=1, Subject="Chemistry", Marks=80},
                new{Student=1, Subject="Biology", Marks=90},
                new{Student=2, Subject="English", Marks=4},
                new{Student=2, Subject="Maths", Marks=5},
                new{Student=2, Subject="Science", Marks=6},
                new{Student=2, Subject="Physics", Marks=7},
                new{Student=2, Subject="Chemistry", Marks=8},
                new{Student=2, Subject="Biology", Marks=9}
            };

        /*Here the pivot column is the subject and the static column is student
        group the data against the static column(s)*/

        var groups = from d in data
                     group d by d.Student into grp
                     select new
                     {
                         StudentId = grp.Key,
                         Marks = grp.Select(d2 => new { d2.Subject, d2.Marks }).ToArray()
                     };


        /*get all possible subjects into a separate group*/
        var subjects = (from d in data
                        select d.Subject).Distinct();

        DataTable dt = new DataTable();

        /*for static cols*/
        dt.Columns.Add("STUDENT_ID");


        /*for dynamic cols*/
        foreach (var subject in subjects)
        {
            dt.Columns.Add(subject.ToString());
        }

        /*pivot the data into a new datatable*/
        foreach (var g in groups)
        {
            DataRow dr = dt.NewRow();
            dr["STUDENT_ID"] = g.StudentId;

            foreach (var mark in g.Marks)
            {
                dr[mark.Subject] = mark.Marks;
            }
            dt.Rows.Add(dr);
        }   
讽刺将军 2024-09-23 02:10:22

这是我能得到的最接近的结果,但它不是 LINQ...

create table #t
(
    pointid [int],
    doublevalue [float],
    title [nvarchar](50)
)

insert into #t
    select
        distinct top 100
        v.pointid, v.doublevalue, p.title
    from [property] p
        inner join pointvalue v on p.propertyid = v.propertyid
        inner join point pt on v.pointid = pt.pointid
    where v.pointid in (select top 5 p.pointid from point p where p.instanceid = 36132)

declare @fields nvarchar(250)
set @fields = (select STUFF((SELECT N',[' + title + ']' FROM [property] FOR XML PATH('')), 1, 1, N''))
--select @fields

declare @sql nvarchar(500)
set @sql = 'select * from #t
pivot
(
    sum(doublevalue)
    for [title] in ('+@fields+')
) as alias'
--select @sql

exec (@sql)

drop table #t

更关键的是,我只是询问 Property 表中的每个条目,这意味着结果数据透视表中有很多列具有 NULL 值。

This is the closest I could get, but it's not LINQ...

create table #t
(
    pointid [int],
    doublevalue [float],
    title [nvarchar](50)
)

insert into #t
    select
        distinct top 100
        v.pointid, v.doublevalue, p.title
    from [property] p
        inner join pointvalue v on p.propertyid = v.propertyid
        inner join point pt on v.pointid = pt.pointid
    where v.pointid in (select top 5 p.pointid from point p where p.instanceid = 36132)

declare @fields nvarchar(250)
set @fields = (select STUFF((SELECT N',[' + title + ']' FROM [property] FOR XML PATH('')), 1, 1, N''))
--select @fields

declare @sql nvarchar(500)
set @sql = 'select * from #t
pivot
(
    sum(doublevalue)
    for [title] in ('+@fields+')
) as alias'
--select @sql

exec (@sql)

drop table #t

The kicker is that I'm simply asking for every entry in the Property table, meaning there's a lot of columns, in the resulting pivot, which have NULL values.

寄风 2024-09-23 02:10:22

我认为的代码是这样的:

var list = from table in Property
                       group table by table.pid into g
                       select new
                       {
                           pid = g.key,
                           LowPrice = g.Where(w => w.pid== g.key && w.priceType == "low").Select(s => s.value).FirstorDefault(),
                           HighPrice = g.Where(w => w.pid== g.key && w.priceType == "high").Select(s => s.value).FirstorDefault(),
                       };

希望它可以帮助你并祝你有美好的一天。

the code I think is like this:

var list = from table in Property
                       group table by table.pid into g
                       select new
                       {
                           pid = g.key,
                           LowPrice = g.Where(w => w.pid== g.key && w.priceType == "low").Select(s => s.value).FirstorDefault(),
                           HighPrice = g.Where(w => w.pid== g.key && w.priceType == "high").Select(s => s.value).FirstorDefault(),
                       };

Hope it can help you and have a nice day.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文