简体   繁体   中英

How to perform a query using LINQ that must make one column distinct but includes all information of another column

I am currently working on an assignment for class that deals with using LINQ to get information from a database filled with something like:

..StudentName..|..Class..|..GPA..|.....Course.....|..CourseNumber..|..FinalGrade..|..CSCIGPA..
......"D, Kara".....|....SR.... |...3.8...|...CSCI4220...|............4220.........|...........A.........|........3.9......
......"D, Kara".....|....SR.....|...3.8...|...CSCI3110...|...........3110..........|..........A..........|........3.9......
...."R, Cisco".....|....JR.....|...3.1...|...CSCI3010...|...........3030..........|..........B..........|........3.4......
...."R, Cisco".....|....JR.....|...3.1...|...CSCI2070...|...........2070..........|..........C..........|........3.4......
...."R, Cisco".....|....JR.....|...3.1...|...CSCI3030...|...........3030..........|..........B..........|........3.4......
...."A, Barry"......|....FR.....|...4.0...|...CSCI1010...|...........1010..........|..........A..........|........4.0......
...."A, Barry"......|....FR.....|...4.0...|...CSCI2010...|...........2010..........|..........A..........|........4.0......
...."Q, Oliver".....|....SO....|...2.7...|...CSCI2020...|...........2010..........|..........C..........|........2.8......
...."Q, Oliver".....|....SO....|...2.7...|...CSCI2020...|...........2010..........|..........C..........|........2.8......
...."Q, Oliver......|....SO....|...2.7...|...CSCI2030...|...........2030..........|..........C..........|........2.8......
......"H, Roy"......|....SO....|...3.8...|...CSCI2020...|...........2020...........|..........A..........|........3.7......

I haven't included all of the columns, but this is a good sample. Given this input, the query should return a list of students for each class (FR, SO, JR, Senior) ordered by GPA(large to small) and then by CSCIGPA(large to small). Additionally, each student to be displayed should have a concatenated "Course" and "FinalGrade", and each concatenated course and final grade should also be included in the list. For example, the record to display "A, Barry" would be:

"A, Barry", FR, 4.0, CSCI1010A CSCI2010A, 4.0

Note: the individual course numbers "1010 and 2010" form the column CourseNumber are not part of the output.

My biggest problem is figuring out how to get the concatinated course and final grade into the single student line (when I did Distinct() it took off all of the different courses and grades except for the first one). Here is some of the code that I wrote, but I'll admit it's not very good and probably not helpful to this problem since I've already described it.

//method to iterate over all students within student table public IEnumerable<Student> GetAllStudents() { var myquery = databaseEDM.Students .OrderBy(x => x.Class).ThenByDescending(x => x.GPA).ThenByDescending(x => x.CSCIGPA) .ToList().Distinct(); return myquery; }

I haven't ever really done anything with databases or queries before this assignment, so any help would really be appreciated. Please let me know if I need to give any more information to get a proper answer. Thanks.

Other Note: This is just a simple console application that gets information from a database to output.

Here is your working example:

        public IEnumerable<Student> GetAllStudents()
        {
            var myquery = databaseEDM.Students
                .GroupBy(x => new { x.StudentName, x.Class })
                .Select(s => new
                {
                    StudentName = s.Key.StudentName,
                    Class = s.Key.Class,
                    GPA = s.Average(g => g.GPA),
                    Courses = string.Join(" ", s.Select(c => c.Course + c.FinalGrade)),
                    CSCIGPA = s.Average(cs => cs.CSCIGPA)
                })
                .OrderBy(x => x.Class)
                .ThenByDescending(x => x.GPA)
                .ThenByDescending(x => x.CSCIGPA)
                .ToList()
                .Distinct();
            return myquery;
        }

What I did?

I grouped students by StudentName and Class .

Then I selected only properties which you requested in the example.

Then I made average GPA for each group because.

Then I joined Course plus FinalGrade for that group because yo want in one value.

And in the end, I created average CSCIGPA for the group.

I hope that I understood correctly your issue. Your data are not best formatted but this query should help.

Your code expect a class Student and you do not have a Student class in the code posted. In the code below I'm expecting results to be in a datatabe (which you can get from a dataadapter).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("StudentName", typeof(string));
            dt.Columns.Add("Class", typeof(string));
            dt.Columns.Add("GPA", typeof(decimal));
            dt.Columns.Add("Course", typeof(string));
            dt.Columns.Add("CourseNumber", typeof(int));
            dt.Columns.Add("FinalGrade", typeof(string));
            dt.Columns.Add("CSCIGPA", typeof(decimal));

            dt.Rows.Add(new object[] {"D, Kara","SR",3.8,"CSCI4220",4220,"A",3.9});
            dt.Rows.Add(new object[] {"D, Kara","SR",3.8,"CSCI3110",3110,"A",3.9});
            dt.Rows.Add(new object[] {"R, Cisco","JR",3.1,"CSCI3010",3030,"B",3.4});
            dt.Rows.Add(new object[] {"R, Cisco","JR",3.1,"CSCI2070",2070,"C",3.4});
            dt.Rows.Add(new object[] {"R, Cisco","JR",3.1,"CSCI3030",3030,"B",3.4});
            dt.Rows.Add(new object[] {"A, Barry","FR",4.0,"CSCI1010",1010,"A",4.0});
            dt.Rows.Add(new object[] {"A, Barry","FR",4.0,"CSCI2010",2010,"A",4.0});
            dt.Rows.Add(new object[] {"Q, Oliver","SO",2.7,"CSCI2020",2010,"C",2.8});
            dt.Rows.Add(new object[] {"Q, Oliver","SO",2.7,"CSCI2020",2010,"C",2.8});
            dt.Rows.Add(new object[] {"Q, Oliver","SO",2.7,"CSCI2030",2030,"C",2.8});
            dt.Rows.Add(new object[] { "H, Roy", "SO", 3.8, "CSCI2020", 2020, "A", 3.7 });

            var myquery = dt.AsEnumerable()
               .OrderBy(x => x.Field<string>("Class")).ThenByDescending(x => x.Field<decimal>("GPA")).ThenByDescending(x => x.Field<decimal>("CSCIGPA")).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