2010-08-25 11 views
2

J'ai une requête T-SQL 2005 qui retourne:Un pivot dynamique utilisant LINQ est-il possible?

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 

Ce que je voudrais faire est essentiellement pivot sur le terrain displayname, production, espérons:

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 

(Je ne sais pas comment le PropertyID le champ serait sorti, donc je l'ai laissé de côté (espérait qu'il serait simplement assis à côté des champs Prix bas et Prix élevé, pour indiquer leurs ID, mais je ne pense pas que cela fonctionnera.)

Le problème est que le contenu de la displayname champ d'origine est dynamique - il est produit à partir d'une jointure avec un PropertyName' table, so the number of pivoted columns is variable. It could therefore contain Prix élevé , Prix bas , Open and Fermer`, en fonction de ce que la jointure avec cette table renvoie.

Il est, bien sûr, relativement facile (quel que soit le problème que j'aie à écrire la requête initiale!) De produire ce pivot dans une requête fixe ou un proc stocké. Cependant, est-il possible d'obtenir LINQ pour générer une requête SQL qui nommerait chaque colonne à produire plutôt que d'avoir à écrire une requête dynamique (probablement dans une procédure stockée) qui répertorie les noms de colonnes?

Merci,

Matt.

Répondre

0

C'est le plus proche que je pouvais obtenir, mais ce n'est pas 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 ('[email protected]+') 
) as alias' 
--select @sql 

exec (@sql) 

drop table #t 

Le botteur est que je demande simplement pour chaque entrée dans la table de la propriété, ce qui signifie qu'il ya beaucoup de colonnes, dans le pivot résultant, qui ont des valeurs NULL.

5

Je vais vous donner un échantillon avec des données différentes (dont j'avais besoin). Vous pouvez adapter cela à vos besoins. Notez que seules deux requêtes linq sont utilisées, la plupart des autres fluff étant de convertir une liste en une donnée.

  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

Cela peut-il être retourné dans un 'IList' ou 'IQueryable'? – uikrosoft

0

le code que je pense est comme ceci:

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

L'espoir peut vous aider et avoir une belle journée.