简体   繁体   中英

C# Linq using distinct with union

I have a table in db as :

Id Name   Stream  Version   UId  Tab    Key    Value  CreatedOn   CreatedBy
1  Name1   GOP      1       U1   Tab1   co      1     07/01/2018  S, Adam
2  Name1   GOP      1       U2   Tab1   co      1     07/03/2018  S, Adam
3  Name1   GOP      1       U3   Tab2   st      2     07/03/2018  S, Adam
4  Name1   GOP      2       OR   Tab1   co      1     07/02/2018  P, Silver
5  Name2   GOP      1       OR   Tab1   co      1     07/02/2018  P, Silver
6  Name3   GOP      0       OR1  Tab0   coe     1     07/02/2018  S, Adam
7  Name3   GOP      0       OR2  Tab1   coe     1     07/02/2018  S, Adam
8  Name2   LNT      3       NE   Tab1   st      4     07/01/2018  P, Silver
9  Name2   LNT      3       NE1  Tab1   co      2     07/01/2018  P, Silver
10 Name2   LNT      2       NE2  Tab1   st      3     07/01/2018  P, Silver
11 Name2   LNT      0       NE   Tab9   co      5     07/01/2018  R, Henry
12 Name3   TTE      0       TT   Tab1   ee      2     07/02/2018  R. Henry
13 Name3   TTE      0       T1   Tab1   ee      2     07/02/2018  R. Henry

I want to write a query that would give me the highest version of set together with distinct version 0.

For this I wrote the query as but this does not get my desired output:

var data = response.GroupBy(x => new { x.Name, x.Stream })
           .SelectMany(g => g.OrderByDescending(row => row.Version).Take(1)) //This gives highest version 
           .Union(response.Where(x => int.Parse(x.Version) == 0)) // This gives version 0
           .OrderByDescending(o => o.CreatedOn).ToList();

Desired Output On UI

Id Name   Stream  Version   CreatedOn   CreatedBy                         
4  Name1   GOP      2       07/02/2018  P, Silver   //This is shown as 2 is the highest version for Name1 & GOP combination
5  Name2   GOP      1       07/02/2018  P, Silver   //This is shown as Name & Stream combination is different 
6  Name1   GOP      0       07/02/2018  S, Adam     //Version 0 is always shown - Combination of Name & Stream may or may not have more than one 0 version
8  Name2   LNT      3       07/01/2018  P, Silver   //This is shown as 3 is the highest version for Name2 & LNT combination
11 Name2   LNT      0       07/01/2018  R, Henry    //Version 0 is always shown 
12 Name3   TTE      0       07/02/2018  R, Henry    //Version 0 is always shown

On the UI I am trying to just show the trimmed down version of a set. When the user clicks on that set I would then show details for all the individual sets within the set.

Right now I only struck with how to update my query so I can get my desired result.

----Updated---

Right now what I got working is individual lists:

 var data1 = response.GroupBy(x => new { x.Name, x.Stream})
              .SelectMany(g => g.OrderByDescending(row => row.Version).Take(1))
              .Where(x => int.Parse(x.Version) != 0)
              .OrderByDescending(o => o.CreatedOn).ToList();

The above gives me all latest versions for a given name and stream.

var data2 = response.GroupBy(x => new { x.Name, x.Stream})
             .Select(g => g.First())
             .Where(x => int.Parse(x.Version) == 0)
             .OrderByDescending(o => o.CreatedOn).ToList();

The above gives me all 0 versions for a given name and stream.

I think these individual lists works fine at the moment, but how to merge them.

Is there a way to join/merge these lists together so as to return just a single set. Or if there is a way to merge these 2 linq queries together.

---Updated-----

    var set1 = response.GroupBy(x => new { x.Name, x.Stream})
                .SelectMany(g => g.OrderByDescending(row => row.Version).Take(1))
               .Where(x => int.Parse(x.Version) != 0).ToList();

    var set2 = response.GroupBy(x => new { x.Name, x.Stream, x.Version})
                       .Select(g => g.First())
                       .Where(x => int.Parse(x.Version) == 0).ToList();

    var setmerged = set1.Union(set2).OrderByDescending(o => o.CreatedOn).ToList();

Got it working by above not sure if this is an clean solution.

Wrong use of DISTINCT

This doesn't make sense. DISTINCT is used to filter duplicate rows, which they aren't as only the version number is the same. Where should the DBS know from, which CreatedOn value it should use?

Better solution

What you want is to use GROUP BY in order to group everything with the same version value. Be aware that you'll need to use an aggregate function like MAX() on the other columns in order to use it correctly.

So from the looks of your updated question, you want the top one of each distinct version, name and stream.

According to the dataset you've provided, and the result sets you want, there is no need to do anything special for the 0 version because the conditions for grabbing the distinct version should include the 0 version as well.

You haven't really specified what the order of the version should be so for now I'll assume that the one that was most recently updated is the one you want

response.GroupBy(x => new { x.Name, x.Stream, x.Version })
        .SelectMany(g => g.OrderByDescending(row => row.CreatedOn).Take(1))
        .ToList();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM