现在的位置: 首页 > 综合 > 正文

2012-09-02 09:29 SQL、LINQ、Lambda 三种用法

2012年12月15日 ⁄ 综合 ⁄ 共 11343字 ⁄ 字号 评论关闭

颜色注释: SQL LinqToSql Lambda QA
1、 查询Student表中的所有记录的Sname、Ssex和Class列。
select sname,ssex,class from student
Linq:
    from s in Students
    select new {
        s.SNAME,
        s.SSEX,
        s.CLASS
    }
Lambda:
    Students.Select( s => new {
        SNAME = s.SNAME,SSEX = s.SSEX,CLASS = s.CLASS
    })

2、 查询教师所有的单位即不重复的Depart列。
select distinct depart from teacher
Linq:
    from t in Teachers.Distinct()
    select t.DEPART
Lambda:
    Teachers.Distinct().Select( t => t.DEPART)
3、 查询Student表的所有记录。
select * from student
Linq:
    from s in Students
    select s
Lambda:
    Students.Select( s => s)

4、 查询Score表中成绩在60到80之间的所有记录。
select * from score where degree between 60 and 80
Linq:
    from s in Scores
    where s.DEGREE >= 60 && s.DEGREE < 80
    select s
Lambda:
    Scores.Where( 
        s => (
                s.DEGREE >= 60 && s.DEGREE < 80 
             )
    )
5、 查询Score表中成绩为85,86或88的记录。
select * from score where degree in (85,86,88)
Linq:
In
    from s in Scores
    where (
            new decimal[]{85,86,88}
          ).Contains(s.DEGREE)
    select s
Lambda:
    Scores.Where( s => new Decimal[] {85,86,88}.Contains(s.DEGREE))
Not in
    from s in Scores
    where !(
            new decimal[]{85,86,88}
          ).Contains(s.DEGREE)
    select s
Lambda:
    Scores.Where( s => !(new Decimal[]{85,86,88}.Contains(s.DEGREE)))
    Any()应用:双表进行Any时,必须是主键为(String)
    CustomerDemographics CustomerTypeID(String)
    CustomerCustomerDemos (CustomerID CustomerTypeID) (String)
    一个主键与二个主建进行Any(或者是一对一关键进行Any)
    不可,以二个主键于与一个主键进行Any
    
    from e in CustomerDemographics
    where !e.CustomerCustomerDemos.Any()
    select e
    
    from c in Categories
    where !c.Products.Any()
    select c
6、 查询Student表中"95031"班或性别为"女"的同学记录。
select * from student where class ='95031' or ssex= N'女'
Linq:
    from s in Students
    where s.CLASS == "95031" 
       || s.CLASS == "女"
    select s
Lambda:
    Students.Where(s => ( s.CLASS == "95031" || s.CLASS == "女"))

7、 以Class降序查询Student表的所有记录。
select * from student order by Class DESC
Linq:
    from s in Students
    orderby s.CLASS descending
    select s
Lambda:
    Students.OrderByDescending(s => s.CLASS)
8、 以Cno升序、Degree降序查询Score表的所有记录。
select * from score order by Cno ASC,Degree DESC
Linq:(这里Cno ASC在linq中要写在最外面)
    from s in Scores
    orderby s.DEGREE descending
    orderby s.CNO ascending 
    select s
Lambda:
    Scores.OrderByDescending( s => s.DEGREE)
          .OrderBy( s => s.CNO)

9、 查询"95031"班的学生人数。
select count(*) from student where class = '95031'
Linq:
    (    from s in Students
        where s.CLASS == "95031"
        select s
    ).Count()
Lambda:
    Students.Where( s => s.CLASS == "95031" )
                .Select( s => s)
                    .Count()
10、查询Score表中的最高分的学生学号和课程号。
select distinct s.Sno,c.Cno from student as s,course as c ,score as sc 
where s.sno=(select sno from score where degree = (select max(degree) from score))
and c.cno = (select cno from score where degree = (select max(degree) from score))
Linq:
    (
        from s in Students
        from c in Courses
        from sc in Scores
        let maxDegree = (from sss in Scores
                        select sss.DEGREE
                        ).Max()
        let sno = (from ss in Scores
                where ss.DEGREE == maxDegree
                select ss.SNO).Single().ToString()
        let cno = (from ssss in Scores
                where ssss.DEGREE == maxDegree
                select ssss.CNO).Single().ToString()
        where s.SNO == sno && c.CNO == cno
        select new {
            s.SNO,
            c.CNO
        }
    ).Distinct()
操作时问题?执行时报错: where s.SNO == sno(这行报出来的) 运算符"=="无法应用于"string"和"System.Linq.IQueryable<string>"类型的操作数
解决:
原:let sno = (from ss in Scores
                where ss.DEGREE == maxDegree
                select ss.SNO).ToString()
Queryable().Single()返回序列的唯一元素;如果该序列并非恰好包含一个元素,则会引发异常。 
解:let sno = (from ss in Scores
                where ss.DEGREE == maxDegree
                select ss.SNO).Single().ToString()
11、查询'3-105'号课程的平均分。
select avg(degree) from score where cno = '3-105'
Linq:
    (
        from s in Scores
        where s.CNO == "3-105"
        select s.DEGREE
    ).Average()
Lambda:
    Scores.Where( s => s.CNO == "3-105")
            .Select( s => s.DEGREE)
                .Average()

12、查询Score表中至少有5名学生选修的并以3开头的课程的平均分数。
select avg(degree) from score where cno like '3%' group by Cno having count(*)>=5
Linq:
        from s in Scores
        where s.CNO.StartsWith("3")
        group s by s.CNO
        into cc
        where cc.Count() >= 5
        select cc.Average( c => c.DEGREE)
Lambda:
    Scores.Where( s => s.CNO.StartsWith("3") )
            .GroupBy( s => s.CNO )
              .Where( cc => ( cc.Count() >= 5) )
                .Select( cc => cc.Average( c => c.DEGREE) )
Linq: SqlMethod
like也可以这样写:
    s.CNO.StartsWith("3") or SqlMethods.Like(s.CNO,"%3")
13、查询最低分大于70,最高分小于90的Sno列。
select sno from score group by sno having min(degree) > 70 and max(degree) < 90
Linq:
    from s in Scores
    group s by s.SNO
    into ss
    where ss.Min(cc => cc.DEGREE) > 70 && ss.Max( cc => cc.DEGREE) < 90
    select new
    {
        sno = ss.Key
    }
Lambda:
    Scores.GroupBy (s => s.SNO)
               .Where (ss => ((ss.Min (cc => cc.DEGREE) > 70) && (ss.Max (cc => cc.DEGREE) < 90)))
                   .Select ( ss => new {
                                        sno = ss.Key
                                     })
14、查询所有学生的Sname、Cno和Degree列。
select s.sname,sc.cno,sc.degree from student as s,score as sc where s.sno = sc.sno
Linq:
    from s in Students
    join sc in Scores
    on s.SNO equals sc.SNO
    select new
    {
        s.SNAME,
        sc.CNO,
        sc.DEGREE
    }
Lambda:
    Students.Join(Scores, s => s.SNO,
                          sc => sc.SNO, 
                          (s,sc) => new{
                                              SNAME = s.SNAME,
                                            CNO = sc.CNO,
                                            DEGREE = sc.DEGREE
                                          })
15、查询所有学生的Sno、Cname和Degree列。
select sc.sno,c.cname,sc.degree from course as c,score as sc where c.cno = sc.cno
Linq:
    from c in Courses
    join sc in Scores
    on c.CNO equals sc.CNO
    select new
    {
        sc.SNO,c.CNAME,sc.DEGREE
    }
Lambda:
    Courses.Join ( Scores, c => c.CNO, 
                             sc => sc.CNO, 
                             (c, sc) => new 
                                        {
                                            SNO = sc.SNO, 
                                            CNAME = c.CNAME, 
                                            DEGREE = sc.DEGREE
                                        })
16、查询所有学生的Sname、Cname和Degree列。
select s.sname,c.cname,sc.degree from student as s,course as c,score as sc where s.sno = sc.sno and c.cno = sc.cno
Linq:
    from s in Students
    from c in Courses
    from sc in Scores
    where s.SNO == sc.SNO && c.CNO == sc.CNO
    select new { s.SNAME,c.CNAME,sc.DEGREE }

Lambda:

Courses.Join ( Scores, c => c.CNO, 
                             sc => sc.CNO, 
                             (c, sc) => new 
                                        {
                                            SNO = sc.SNO, 
                                            CNAME = c.CNAME, 
                                            DEGREE = sc.DEGREE
                                        }).Join(Students, S => S.SNO,

A=>A.SNO,

(S,A)=>new

{

 SNO = A.SNO, 
        CNAME = A.CNAME, 
         DEGREE = A.DEGREE

})

一、条件操作符

条件操作符Where类似于SQL中的WHERE子句,用于实现条件查询。下列扩展方法表达式查询满足条件“角色不为空”的用户集合:

var user = db.Users.Where(o => o.Roles != null);

对应的标准查询操作符表达式为:

1 var users = from o in db.Users
2             where o.Roles != null
3             select o;

二、投影操作符

投影操作符Select类似于SQL中的SELECT子句,将对象投影为一个匿名类型实例,用于控制指定查询迭代器显示或者处理的对象属性。另外,需要注意的是,扩展方法表达式中的Select操作符并非必须的,省略模式下,会返回完整的被投影对象。下列扩展方法表达式将用户的帐号和密码信息投影为一个匿名类型:

var users = db.Users.Select(o => new { o.Account, o.Password });

对应的标准查询操作符表达式为:

1 var users = from o in db.Users
2             select new { o.Account, o.Password };

三、分区操作符

分区操作符实现对象的分区操作。其中,Take操作符类似于SQL中的TOP操作符,下列扩展方法表达式返回前5个用户对象:

var users = db.Users.OrderBy(o => o.Roles.Count).Take(5);

Skip操作符用于跳过指定个数对象并返回序列中的剩余对象,下列扩展方法表达式返回除前10个用户外的剩余用户:

var users = db.Users.OrderBy(o => o.Roles.Count).Skip(10);

TakeWhile操作符用于返回条件表达式值为真时的相邻元素集合,下列扩展方法表达式返回第一个拥有3个角色的用户之前的所有用户集合:

var users = db.Users.OrderBy(o => o.Roles.Count).TakeWhile(o => o.Roles.Count == 3);

SkipWhile操作符用于跳过条件表达式值为真时的元素,并返回剩下的元素集合,下列扩展方法表达式返回第一个拥有3个角色的用户之后的所有用户集合:

var users = db.Users.OrderBy(o => o.Roles.Count).SkipWhile(o => o.Roles == 3);

四、排序操作符

排序操作符实现对象的排序功能,包括OrderBy、OrderByDescending、ThenBy、ThenByDescending和Reverse五个操作符。其中OrderBy操作符实现对象的升序排列,相当于SQL中的ORDER BY ASC子句,下列扩展方法表达式实现用户按拥有的角色数进行升序排列:

var users = db.Users.OrderBy(o => o.Roles.Count);

对应的标准查询操作符表达式为:

1 var users = from o in db.Users
2             orderby o.Roles.Count
3             select o;

OrderByDescending操作符实现对象的降序排列,相当于SQL中的ORDER BY DESC子句,下列扩展方法表达式实现用户按拥有的角色数进行降序排列:

var users = db.Users.OrderByDescending(o => o.Roles.Count);

对应的标准查询操作符表达式为:

1 var users = from o in db.Users
2             orderby o.Roles.Count descending
3             select o;

ThenBy、ThenByDescending和Reverse操作符只能针对IOrderedEnumerable接口对象使用,所以一般紧跟在OrderBy/OrderByDesending操作符方法后使用。ThenBy操作符由编译器翻译为对OrderBy操作符的再次调用;ThenByDescending操作符由编译器翻译为对OrderByDescending操作符的再次调用;Reverse操作符实现对象的排序反向。这里不再一一举例。

五、分组操作符

分组操作符GroupBy类似于SQL中的GROUP BY子句,实现对象的分组操作。下列扩展方法表达式实现用户对象按拥有的角色数量进行分组:

var users = db.Users.GroupBy(o => o.Roles.Count);

对应的标准查询操作符表达式为:

1 var users = from o in db.Users
2             group o by o.Roles.Count into g
3             select new { RoleCount = g.Key, Group = g };

六、集合操作符

集合操作符包括Distinct、Union、intersect和Except四个操作符,除Distinct外,其他三个操作符都可将两个序列组合成一个序列。Distinct操作符类似于SQL中的DISTINCT关键字,用于删除序列中具有重复值的对象。下列扩展方法表达式实现将用户角色中的重复角色删除功能:

var roles = user.Roles.Distinct();

Union操作符类似于SQL中的UNION关键字,用于求具有同样结构的两个序列的并集。下列扩展方法表达式实现将用户1和用户2所拥有的角色组合成一个角色集合,并排除其中重复的角色:

var roles = user1.Roles.Union(user2.Roles);

Intersect操作符类似于SQL中的INTERSECT关键字,用于求具有同样结构的两个序列的交集。下列扩展方法表达式返回用户1和用户2都具有的角色集合:

var roles = user1.Roles.Intersect(user2.Roles);

Except操作符类似于SQL中的EXCEPT关键字,用于返回第一个序列中有、但第二个序列中没有的对象集合。下列扩展方法表达式返回用户1拥有,而用户2没有的角色集合:

var roles = user1.Roles.Except(user2.Roles);

七、元素操作符

元素操作符包括两组操作符,分别是用于从一个IEnumerable<T>序列中返回满足条件的单个对象或无满足条件对象时抛异常的First、Last和Single操作符,以及返回满足条件的单个对象或无满足条件对象时返回空对象的FirstOrDefault、LastOrDefault和SingleOrDefault操作符。其中First和FirstOrDefault操作符用于返回第一个满足条件的对象。下列扩展方法表达式返回第一个拥有三个角色的用户:

var user = db.Users.FirstOrDefault(o => o.Roles.Count == 3);

Last和LastOrDefault操作符用于返回最后一个满足条件的对象。下列扩展方法表达式返回最后一个拥有三个角色的用户:

var user = db.Users.LastOrDefault(o => o.Roles.Count == 3);

Single和SingleOrDefault操作符用于返回满足条件的序列中的唯一元素,如果序列中包含不止一个元素,将会抛异常。下列扩展方法表达式返回帐号为“Apollo”的唯一用户,如果有多个用户帐号都为“Apollo”,则抛异常:

var user = db.Users.SingleOrDefault(o => o.Account == "Apollo");

八、量词操作符

量词操作符包括 Any、All和Contains三个操作符,用于检查序列中是否有一些对象或所有对象满足条件。其中,Any操作符用于检查序列中是否有任何一个对象满足条件。下列扩展方法表达式当有任何一个用户拥有三个角色时返回真,否则返回假:

var result = db.Users.Any(o => o.Roles.Count == 3);

All操作符用于检查序列中是否所有对象均满足条件。下列扩展方法表达式当所有用户均拥有三个角色时返回真,否则返回假:

var result = db.Users.All(o => o.Roles.Count == 3);

Contains操作符用于检查序列中是否包含指定的对象。下列扩展方法表达式当集合中包含用户1则返回真,否则返回假:

var result = db.Users.Where(o => o.Roles.Count == 3).Contains(user1);

九、聚集操作符

聚集操作符包括Count、Min、Max、Sum和Average等多个操作符,用于对对象集合进行统计计算。其中,Count操作符类似于SQL中的COUNT关键字,用于计算序列中满足条件的对象个数。下列扩展方法表达式返回拥有3个角色的用户数量:

var result = db.Users.Count(o => o.Roles.Count == 3);

Min操作符类似于SQL中的MIN关键字,用于返回按条件计算的最小值。下列扩展方法表达式返回拥有最少角色数量的用户所拥有的角色数量:

var result = db.Users.Min(o => o.Roles.Count);

Max操作符类似于SQL中的MAX关键字,用于返回按条件计算的最大值。下列扩展方法表达式返回拥有角色数量最多的用户所拥有的角色数量:

var result = db.Users.Max(o => o.Roles.Count);

Sum操作符类似于SQL中的SUM关键字,用于返回按条件计算的总数。下列扩展方法表达式返回已赋予用户的所有角色总数:

var result = db.Users.Sum(o => o.Roles.Count);

Average操作符类似于SQL中的AVERAGE关键字,用于返回按条件计算的平均值。下列扩展方法表达式,用于返回用户所拥有的角色平均数:

var result = db.Users.Average(o => o.Roles.Count);

抱歉!评论已关闭.