10
votes

Linq à la version SQL du groupe avec Rollup

J'essaie de réécrire un vieil SQL dans Linq à SQL. J'ai une SPUCT avec un groupe avec le rouleau, mais je ne suis pas sûr de ce que l'équivalent Linq serait. Linq a une groupeby mais il ne semble pas que cela prend en charge le rouleau.

Un exemple simplifié des résultats que j'essaie de devenir quelque chose comme ceci: xxx

Toutes idées sur la manière dont je pourrais obtenir ces résultats à l'aide de Linq à SQL?


0 commentaires

4 Réponses :


4
votes

Je l'ai eu! Une groupe génériquebywithbriollup. Il ne s'agit que de deux colonnes, mais pourrait facilement être étendu pour soutenir davantage. J'aurai probablement une autre version qui accepte trois colonnes. Les classes de clés / méthodes sont regroupant , groupebymany () et groupebywithrollup (). Les méthodes sous-totales () et grand-tobintes () sont des assistants lorsque vous utilisez réellement le groupeBywithRollup (). Vous trouverez ci-dessous le code, suivi d'un exemple de comment l'utiliser.

class Program
{
    static void Main(string[] args)
    {
        IQueryable<CustomObject> dataItems = (new[]
        {
            new CustomObject { City = "Seattle", Plan = "Plan B", Charges = 20 },
            new CustomObject { City = "Seattle", Plan = "Plan A", Charges = 10 },
            new CustomObject { City = "Seattle", Plan = "Plan B", Charges = 20 },
            new CustomObject { City = "Seattle", Plan = "Plan A", Charges = 10 },
            new CustomObject { City = "Seattle", Plan = "Plan A", Charges = 10 },
            new CustomObject { City = "Seattle", Plan = "Plan A", Charges = 10 },
            new CustomObject { City = "Portland", Plan = "Plan A", Charges = 10 },
            new CustomObject { City = "Portland", Plan = "Plan A", Charges = 10 },
            new CustomObject { City = "Portland", Plan = "Plan C", Charges = 30 },
            new CustomObject { City = "Portland", Plan = "Plan C", Charges = 30 },
            new CustomObject { City = "Portland", Plan = "Plan C", Charges = 30 }
        }).AsQueryable();

        List<CustomObject> results = dataItems.OrderBy(item => item.City).ThenBy(item => item.Plan).GroupByWithRollup(
            item => item.City,
            item => item.Plan,
            (primaryGrouping, secondaryGrouping) => new CustomObject
            {
                City = primaryGrouping.Key,
                Plan = secondaryGrouping.Key,
                Count = secondaryGrouping.Count(),
                Charges = secondaryGrouping.Sum(item => item.Charges)
            },
            item => new CustomObject
            {
                City = item.Key,
                Plan = "All",
                Count = item.SubTotal(subItem => subItem.Count),
                Charges = item.SubTotal(subItem => subItem.Charges)
            },
            items => new CustomObject
            {
                City = "All",
                Plan = "All",
                Count = items.GrandTotal(subItem => subItem.Count),
                Charges = items.GrandTotal(subItem => subItem.Charges)
            }
            );
        foreach (var result in results)
            Console.WriteLine(result);

        Console.Read();
    }
}

class CustomObject
{
    public string City { get; set; }
    public string Plan { get; set; }
    public int Count { get; set; }
    public decimal Charges { get; set; }

    public override string ToString()
    {
        return String.Format("{0} - {1} ({2} - {3})", City, Plan, Count, Charges);
    }
}


2 commentaires

Bah, il y a toujours des bugs là-bas. Lorsque je l'exécute contre les données SQL réelles, il jette des exceptions parce que je dois utiliser l'expression > au lieu de Just Func <>. Je ne peux pas non plus utiliser la syntaxe "de x en y" avec des expressions. Cet article a aidé à ce que: richardbushnell.net/index.php/2008/01/16/... . Donc, j'ai encore besoin d'obtenir cela nettoyé.


Cette approche s'est avérée beaucoup plus complexe que nécessaire. Je n'ai pas pu obtenir le regroupement entièrement du côté SQL. En fin de compte, j'ai abandonné cette approche et avons eu la solution acceptée beaucoup plus simple.



13
votes

J'ai compris une solution beaucoup plus simple. J'essayais de rendre cela plus compliqué que nécessaire. Plutôt que d'avoir besoin de 3-5 classes / méthodes, je n'ai besoin que d'une méthode.

Fondamentalement, vous faites votre tri et regroupez-vous, puis appelle sans fil () pour obtenir une liste <> des éléments avec des sous-totaux et un total total. Je ne pouvais pas comprendre comment générer les sous-totaux et le total du total du côté SQL afin d'être effectué avec Linq aux objets. Voici le code: xxx

et un exemple de comment l'utiliser: xxx


0 commentaires

2
votes

@ecyrb, bonjour à partir de cinq ans plus tard!

Je ne suis que peu familier avec Linq à SQL ci-dessus et au-delà de la linq standard (aux objets). Cependant, étant donné que vous avez une balise "LINQ" séparée de votre étiquette "LINQ-2-SQL", car vous semblez être principalement intéressé par les résultats (par opposition à l'enregistrement des modifications avec la base de données), et parce que c'est le seul Fonction de regroupement de SQL Server de SQL Server, je vais offrir ma propre solution alternative à personne aujourd'hui avec un besoin similaire. P>

essentiellement, mon L'approche consiste à créer un ".groupby (). Syntaxe de charabia () similaire à la" Ordinateur .Orderby (). Syntaxe () ". Mon extension s'attend à une collection d'objets Igrouping - le résultat que vous obtenez de l'exécution de "GROUPBY ()" - comme source. Il prend ensuite la collection et les déclineille pour revenir à l'objet d'origine avant de grouper. Enfin, il regroupe les données conformément à la nouvelle fonction de regroupement, produisant un autre ensemble d'objets Igrouping et ajoute les objets nouvellement groupés dans l'ensemble des objets source. P>

var rollItUp = dataItems
    .GroupBy(g=> new {g.City, g.Plan})
        .ThenBy(g=> new {g.City, Plan = (string) null})
        .ThenBy(g=> new {City = (string) null, Plan = (string) null})
    .Select(s=> new CustomObject {
        City = s.Key.City, 
        Plan = s.Key.Plan, 
        Count = s.Count(),
        Charges = s.Sum(a=> a.Charges)})
    .OrderBy(o=> o.City) // This line optional
        .ThenBy(o=> o.Plan); // This line optional


0 commentaires

0
votes

Une solution assez intéressante est fournie ici

​​ https://blogs.msdn.microsoft.com/mitsu/2007/12/21/playing-with-linq-grouping-groupbymany/ p>

Il décrit comment Effectuez Groupeby par plusieurs propriétés. I.E: P>

var result = customers.GroupByMany(c => c.Country, c => c.City);


0 commentaires