设为首页 收藏本站
查看: 693|回复: 0

[经验分享] 基础知识(C#语法、数据库SQL Server)回顾与总结

[复制链接]

尚未签到

发表于 2017-12-7 19:42:46 | 显示全部楼层 |阅读模式
前言
  已经有大概一个多月没有更新博客,可能是开始变得有点懒散了吧,有时候想写,但是又需要额外投入更多的时间去学习,感觉精力完全不够用啊,所以为了弥补这一个多月的潜水,决定写一篇,衔接9月未写博客的空缺。

无需定义实体,返回object类型,如何获取属性值?
  这样的场景在下拉列表中很常见,在下拉列表中我们只需要Id和Name两个字段,无需其他字段,同时也是为了节约流量,例如实体和数据如下:



    public class Department
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime CreatedTime { get; set; }
public string Contact { get; set; }
public string ContactUser { get; set; }
}


            var deparments = new List<Department>()
{
new Department(){ Id=1,Name="department1",CreatedTime=DateTime.Now,Contact="13682687787",ContactUser="Tom"},
new Department(){ Id=2,Name="department2",CreatedTime=DateTime.Now,Contact="13682687788",ContactUser="Jeffcky"},
new Department(){ Id=3,Name="department3",CreatedTime=DateTime.Now,Contact="13682687783",ContactUser="Lily"},
new Department(){ Id=4,Name="department4",CreatedTime=DateTime.Now,Contact="13682687782",ContactUser="Jim"},
new Department(){ Id=5,Name="department5",CreatedTime=DateTime.Now,Contact="13682687781",ContactUser="Allen"},
};
  此时为了再额外定义另外的实体,我们通过匿名类型来进行转换



        static IEnumerable<object> Change(List<Department> departments)
{
var changeDepartments = departments.Select(d => new
{
id = d.Id,
name = d.Name
});
return changeDepartments;
}
  将上述集合传入到该Change方法中则返回集合中包含id和name的列,这样在下拉列表就能很好的显示,但是如果用户选择了所在部门,下一次再次进行编辑时需要在该转换集合中得到用户的id和name,此时集合返回类型为object,我们如何得到其中的属性id和用户id进行比对呢,我们来看看以下两种方法。

反射
  反射应该是我们首先能够想到的方式了,获取该实体类型的属性并获取其值。例如我们要在上述Change方法返回的集合中获取到id=1的对象,我们通过如下反射来获取。



  var changes = Change(deparments);
var specialDepartment = changes.FirstOrDefault(d => Convert.ToInt32(d.GetType().GetProperty("id").GetValue(d)) == 1);
DSC0000.png


dynamic关键字
  上述实现是最原始的方式,当dynamic关键字出世之后,我们可以直接将集合中的object类型转换为dynamic动态对象,在运行时让编译器自己去计算,如此一来上述的实现可以更加简洁实现。



           var changes = Change(deparments);
var specialDepartment = changes.FirstOrDefault(d => ((dynamic)d).id == 1);
DSC0001.png

  虽然上述利用dynamic关键字实现看似很简洁但是也有其缺点,类似于JavaScript中动态类型,它是区分大小写的,要是我们将id写成Id直接抛出异常,如下:



  var specialDepartment = changes.FirstOrDefault(d => ((dynamic)d).Id == 1);
DSC0002.png

  为了这样避免出错,而且我们还是需要有智能提示,那就老老实实写一个专门针对下拉列表的转换类,也未尝不可。



    public class SelectItem
{
public int Id { get; set; }
public string Name { get; set; }
}
数据排名
  排名这个也是常见不能再常见的场景了,例如在微信运动中就有截止到每天到十点每天所走步数好友的排名,场景有几种对应的实现方式也有几种,我们来看看。建立如下简单示例表。
DSC0003.png


不同等分数排名
  不同等分数即分数都不一样,如下
DSC0004.png

  首先我们利用Row_Number()函数来实现排名。



SELECT UserId,Score,
ROW_NUMBER() OVER(ORDER BY Score DESC) AS [Rank]
FROM dbo.Ranks
DSC0005.png

  这样我们就可以获取到某个用户所在排名为多少,这只是针对没有同样的分数而言,要是分数有一样的呢,Row_Number函数还适用?

同等分数并列排名
  我们将数据修改成如下:
DSC0006.png

  再来利用Row_Number来进行排名。
DSC0007.png

  此时分数同样为90则排名一个为第三名,另个却为第四名,用户表示我不服,分数不一样,而且没有其他维度的判断逻辑,怎么我就变成第四名了呢,不应该是并列第三名么。这是程序员小哥的bug。我不听,我不听。下面再来设计一个课程得分的表ExamResult。
DSC0008.png

DSC0009.png

  并列分数排名又分为两种场景,比如上述学生Sam的数学和科学都是为90,则并列第一名,到了社会这门学科是第三名,还是第二名呢,这就看实际应用场景,若是第三名我们就需要用RANK函数来排名。



SELECT  Name ,
Subject ,
Marks ,
RANK() OVER (PARTITION BY name ORDER BY Marks DESC ) Rank
FROM    ExamResult
ORDER BY name ,
subject
DSC00010.png

  若是没有空缺排名则利用DENSE_RANK函数来实现。



SELECT  Name ,
Subject ,
Marks ,
DENSE_RANK() OVER ( PARTITION BY name ORDER BY Marks DESC ) Rank
FROM    ExamResult
ORDER BY name
DSC00011.png

  由上我们知道关于SQL Server中RANK和DENSE_RANK函数的区别在于DENSE_RANK函数没有排名空缺。在大部分场景下都需要考虑并列排名的情况,其ROW_NUMBER函数不再适用,除非明确知道排名中不会存在分数并列的情况,否则谨慎适用。

删除数据重复
  如果数据库表设计不够合理,或者说出现并发很容易导致插入重复情况,此时我们去尝试删除数据重复的表。我们首先创建如下测试表。



CREATE TABLE DuplicateRows
(
Id INT ,
Name VARCHAR(20)
)
INSERT INTO DuplicateRows
VALUES ( 1, 'Andy' )
INSERT INTO DuplicateRows
VALUES ( 1, 'Andy' )
INSERT INTO DuplicateRows
VALUES ( 2, 'Bill' )
INSERT INTO DuplicateRows
VALUES ( 2, 'Bill' )
INSERT INTO DuplicateRows
VALUES ( 2, 'Bill' )
INSERT INTO DuplicateRows
VALUES ( 3, 'Chris' )
DSC00012.png

  我们看到如上数据Name为Andy的数据重复两次,同时Name为Bill的数据重复三次。关于数据重复删除方式总结起来有四种方式,我们一起来总结下。

借助临时表(方式一)



SELECT DISTINCT
*
INTO    #tmp
FROM    [dbo].[DuplicateRows]
DELETE  FROM [dbo].[DuplicateRows]
INSERT  INTO [dbo].[DuplicateRows]
SELECT  *
FROM    #tmp
DROP TABLE #tmp
  上述逻辑很简单,我们查询出不重复的删除并插入到临时表中,然后删除表中数据将临时表中不重复的数据插入到表中即可。
DSC00013.png


RANK() OVER( PARTITION BY)(方式二)
  上述是最简单的方式,若是我们表中有一列和另外一行列不同,此时利用DISTINCT关键字过滤数据将不再起作用。在这种情况下,我们可以添加一列,作为行唯一标识符(自动递增升序)。然后获取每个Id的名称。 如果Rank大于1,则表示它是重复行然后删除。 删除重复的行后,删除唯一列标识。 如下:
  添加唯一标识列且自增长。



  ALTER TABLE [dbo].[DuplicateRows] ADD  sNo INT IDENTITY(1,1)
  利用RANK函数对名称进行分区并进行sNo排序。



  SELECT    * ,
RANK() OVER ( PARTITION BY Id, Name ORDER BY sNo ) [rank]
FROM      [dbo].[DuplicateRows]

DSC00014.png

  此时再删除rank大于1即重复的数据。



DELETE E
FROM   [dbo].[DuplicateRows] E
INNER JOIN ( SELECT * ,
RANK() OVER ( PARTITION BY Id, Name ORDER BY sNo DESC ) [rank]
FROM   [dbo].[DuplicateRows]
) T ON E.sno = t.sno
WHERE  T.[rank] > 1
  最后删除唯一标识列sNo.



ALTER TABLE [dbo].[DuplicateRows]
DROP  COLUMN sNo
DSC00015.png

  完整代码如下:



  ALTER TABLE [dbo].[DuplicateRows] ADD  sNo INT IDENTITY(1,1)
DELETE    E
FROM      [dbo].[DuplicateRows] E
INNER JOIN ( SELECT * ,
RANK() OVER ( PARTITION BY Id, Name ORDER BY sNo DESC ) [rank]
FROM   [dbo].[DuplicateRows]
) T ON E.sno = t.sno
WHERE     T.[rank] > 1
ALTER TABLE [dbo].[DuplicateRows]
DROP  COLUMN sNo
DELELTE TOP(2)(方式三)
  如果我们想删除特定重复的数据,通过DELETE TOP语句来完成,例如删除上述id = 2的重复数据。



DELETE TOP ( 2 )
FROM   [dbo].[DuplicateRows]
WHERE  Id = 2
HAVING COUNT(*) >1(方式四)
  如果我们需要将所有重复的数据都删除,只保留未被删除的数据,利用HAVING COUNT(*) >1完成,若是查询到重复个数大于1则删除。



   DELETE   FROM [dbo].[DuplicateRows]
WHERE    Id IN ( SELECT  Id
FROM    [dbo].[DuplicateRows]
GROUP BY Id
HAVING  COUNT(*) > 1 )
  上述讲到了删除数据重复的四种方式,若是需要查询并过滤数据重复情况,举一反三同样大部分也适用。

总结
  本节讲述一点基础知识,回顾了一下,十一期间有时间会讲讲vue。see u.

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-421902-1-1.html 上篇帖子: Configure Always On Availability Group for SQL Server on RHEL——Red Hat Enterpris 下篇帖子: windows C++实现注销、重启、关机 logoff reboot shutdown
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表