• SQL SERVER 实现相同记录为空显示(多列去除重复值,相同的只显示一条数据)


    sql server语句查询中碰到结果集有重复数据,需要把这个重复数据汇总成一条显示。其余则正常显示。

    使用SQL内置函数 ROW_NUMBER() 加 PARTITION 完成

    ROW_NUMBER() OVER ( PARTITION BY '相同数据字段' ORDER BY GETDATE() ) row

    PARTITION BY和GROUP BY类似。

    GROUP BY会影响行数,针对于所有字段进行一个聚合。

    PARTITION BY则不会影响行数,用做于此处刚刚好。

    例:查询出字段有A、B、C、D、E。其中A代表姓名、B代表年龄、C代码性别、D代表爱好、E代表喜欢游戏。

    其中A、B、C,这三个字段中有重复字段,而D、E则无重复字段。

    那么语句便可以这样写

    SELECT *,ROW_NUMBER() OVER ( PARTITION BY A,B,C ORDER BY GETDATE() ) row FROM tab

    这样你便会看到你的结果中row字段会依据A、B、C三个字段依据不同值分别做一个分组。

    A B C D E row
    小明 18 1 篮球 LOL 1
    小明 18 1 乒乓球 DNF 2
    小黄 18 2 游泳 LOL 1
    小黄 18 2 滑板 QQ飞车 2
    小黄 18 2 跑步 战地五 3
    小孙 18 1 睡觉 剑网三 1

    所以以上数据便是依据PARTITION BY分组所显示行号。

    既然已经得到这样的数据,那么把相同的数据更改为空就很简单了。使用CASE WHEN便可以实现。

    SELECT  CASE WHEN row = 1 THEN T.A
                 ELSE ''
            END A ,
            CASE WHEN row = 1 THEN T.B
                 ELSE ''
            END B ,
            CASE WHEN row = 1 THEN T.C
                 ELSE ''
            END C ,
            T.D ,
            T.E
    FROM    ( SELECT    * ,
                        ROW_NUMBER() OVER ( PARTITION BY A, B, C ORDER BY GETDATE() ) row
              FROM      tab
            ) T

    那么以上语句执行最终结果便是一下表格里的数据:

    A B C D E row
    小明 18 1 篮球 LOL 1
          乒乓球 DNF 2
    小黄 18 2 游泳 LOL 1
          滑板 QQ飞车 2
          跑步 战地五 3
    小孙 18 1 睡觉 剑网三 1

    这样一来就简介多了,SQL SERVER很多内置函数还是非常好用的。

    最后放上一个测试临时表格供大家测试吧!

    CREATE TABLE #tab
        (
          headerNo VARCHAR(10) ,
          machineNO VARCHAR(10) ,
          descrption NVARCHAR(20) ,
          artNo VARCHAR(20) ,
          qty INT ,
          repartno VARCHAR(20) ,
          repqty INT
        )

    插入数据

    insert INTO #tab SELECT 'HD01','0101520',N'电池出问题','102020',2,'102020',2
    insert INTO #tab SELECT 'HD01','0101520',N'电池出问题','101010',2,'202020',2
    insert INTO #tab SELECT 'HD01','0101520',N'电池出问题','126888',2,'102020',2
    insert INTO #tab SELECT 'HD02','01012221',N'D电机故障','102020',2,'102020',2
    insert INTO #tab SELECT 'HD03','12312312',N'突然停机','102020',2,'102020',2
    insert INTO #tab SELECT 'HD03','12312312',N'突然停机','102020',2,'102020',2
    insert INTO #tab SELECT 'HD04','12312344',N'皮带松了','102020',2,'102020',2

    语句查询执行

    SELECT  CASE WHEN row = 1 THEN headerNo
                 ELSE ''
            END headerNo ,
            CASE WHEN row = 1 THEN machineNO
                 ELSE ''
            END machineNO ,
            CASE WHEN row = 1 THEN descrption
                 ELSE ''
            END descrption ,
            artNo ,
            qty ,
            repartno ,
            repqty
    FROM    ( SELECT    * ,
                        ROW_NUMBER() OVER ( PARTITION BY headerNo, machineNO,
                                            descrption ORDER BY GETDATE() ) row
              FROM      #tab
            ) M

    以上测试SQL语句来自博客园以下老哥的文章,它的文章只编写了SQL语句供予测试。

    我加以修改,做了一些理解性的分析。

    https://www.cnblogs.com/panxuguang/p/5668520.html

    后续更新

    PARTITION BY简称分区函数,GROUP BY为聚合函数。
    PARTITION BY的使用之处可以有很多,文章的上半部分查询出来的数据用于报表非常合适。
    但用作于程序中就会显得比较复杂。
    以此可以思考,既然 PARTITION BY是依据当前字段不同的字段做一个分组,不影响数据结构、数据行。
    结合ROW_NUMBER对分组后的数据进行一个排序。这样就可以根据ROU_NUMBER后的字段进行数据查询。
    同时,PARTITION BY 还可以在一个查询语句中针对于多个字段进行查询。但后续的PARTITION BY须携带上前一个字段。
    比如上面例子中再增加一个字段,父母标识。L字段中,0代表自己,1代表母亲,2代表父亲。D和E就表示父母的爱好。
    SELECT  CASE WHEN row = 1 THEN T.A
                 ELSE ''
            END A ,
            CASE WHEN row = 1 THEN T.B
                 ELSE ''
            END B ,
            CASE WHEN row = 1 THEN T.C
                 ELSE ''
            END C ,
         CASE WHEN row2 = 1 THEN T.L
                    ELSE ''
            END F,
            T.D ,
            T.E
    FROM    ( SELECT    * ,
                        ROW_NUMBER() OVER ( PARTITION BY A, B, C ORDER BY GETDATE() ) row,
                        ROW_NUMBER() OVER ( PARTITION BY A, B, C, L ORDER BY GETDATE() ) row2
              FROM      tab
            ) T   

    这样除了第一次的依据A,B,C进行了一个内部分区排序,
    随后第二次操作就会依据A,B,C为参照针对L的不同字段在做一个内部分区排序。数据就是下面的样式
    A B C L D E
    小明 18 1 0 篮球 LOL
            乒乓球 DNF
          2 篮球 吃鸡
            跳伞 黎明杀机
          1 跳绳 和平精英
    小黄 18 2   游泳 LOL
            滑板 QQ飞车
            跑步 战地五
    小孙 18 1   睡觉 剑网三


















    通过PARTITON BY 分区排序之后,你还可以取以什么为条件了前三条,以什么字段为排序的第一条等等操作




  • 相关阅读:
    Centos-ip配置详解
    Selenium-java-js操作日历
    Selenium-java-获取当前时间
    一起学ROS之启动文件及ROS命令汇总
    一起学ROS之通信机制
    一起学ORBSLAM2(1)跑通ORBSLAM2 ubuntu 14.04的运行
    高斯金字塔的思考
    ubuntu下opencv2.4.9和opencv3.1.0的使用
    一起学ROS之安装ROS(ubuntu+ros+opencv2.4.9+kinect V2 安装教程)
    动态规划解决分层图最短路径问题
  • 原文地址:https://www.cnblogs.com/Scholars/p/13447966.html
Copyright © 2020-2023  润新知