Возможен ли динамический разворот с использованием LINQ? - PullRequest
3 голосов
/ 25 августа 2010

У меня есть запрос 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, поэтому я его опустил (надеялся, что оно просто расположится рядом с полями Low Price и High Price, чтобы указать их идентификаторы, но я не думаю, что это сработает.)

Проблема заключается в том, что содержимое исходного поля displayname является динамическим - оно создается из соединения с PropertyName' table, so the number of pivoted columns is variable. It could therefore contain High Price , Low Price , Open and Close`, в зависимости ото том, что возвращает объединение с этой таблицей.

Конечно, относительно легко (независимо от проблемы, с которой я пишу первоначальный запрос!) создать этот стержень в фиксированном запросе или хранимом процессе.Однако возможно ли заставить LINQ сгенерировать SQL-запрос, в котором будет указан каждый столбец, а не записывать динамический (возможно, в хранимой процедуре) запрос, в котором перечислены имена столбцов?

Спасибо

Мат.

Ответы [ 3 ]

6 голосов
/ 16 декабря 2010

Я дам вам образец с другими данными (которые мне нужны). Вы можете адаптировать это к вашим потребностям. Обратите внимание, что используются только два запроса 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);
        }   
0 голосов
/ 27 июня 2012

код, который я думаю, выглядит следующим образом:

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(),
                       };

Надеюсь, это поможет вам и хорошего дня.

0 голосов
/ 25 августа 2010

Это самое близкое, что я мог получить, но это не 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

Кикер в том, что я просто запрашиваю каждую запись в таблице свойств, то есть в результирующем сводном множестве столбцов много значений NULL.

...