• SQL Server ->> 间接实现COUNT(DISTINCT XXX) OVER(PARTITION BY YYY)


    SQL Server 2005版本开始支持了窗口函数(Windowing Function)和OVER字句。SQL Server 2012版本开始支持了窗口函数的ORDER BY字句实现连续/累计聚合功能。但是有个功能到SQL Server 2014版本为止(从目前SQL Server 2016 CTP3来看,还是不支持),就是COUNT(DISTINCT XXX) OVER(PARTITION BY YYY)。

    一直觉得这个事情没有办法用比较巧妙地办法做到,只能是用CROSS APPLY或者循环去把数据集“UNION ALL”起来。今天在Google上找到了一个别人想到的办法,顿时觉得自己怎么那么笨,没有想到这个办法呢。巧妙之处在于用一个带有DENSE_RANK函数的子查询配合MAX函数实现。下面是测试代码:

    CREATE TABLE Foo (
    fookey INT PRIMARY KEY,
    company VARCHAR(30),
    sales_rep VARCHAR(30),
    client VARCHAR(30));
    
    INSERT INTO Foo VALUES(1, 'ABC Corp.', 'Joe', 'Client1');
    INSERT INTO Foo VALUES(2, 'ABC Corp.', 'Joe', 'Client2');
    INSERT INTO Foo VALUES(6, 'ABC Corp.', 'Joe', 'Client2');
    INSERT INTO Foo VALUES(3, 'ABC Corp.', 'Peter', 'Client2');
    INSERT INTO Foo VALUES(4, 'DEF Corp.', 'Joe', 'Client1');
    INSERT INTO Foo VALUES(5, 'DEF Corp.', 'Joe', 'Client3');
    
    SELECT DISTINCT company, sales_rep, client,
    MAX(rk1) OVER(PARTITION BY sales_rep) AS rep_distinct_client_cnt,
    MAX(rk2) OVER(PARTITION BY company) AS company_distinct_client_cnt
    FROM (
    SELECT fookey, company, sales_rep, client,
    DENSE_RANK() OVER(PARTITION BY sales_rep ORDER BY client) As rk1,
    DENSE_RANK() OVER(PARTITION BY company ORDER BY client) As rk2
    FROM Foo) AS F;

    这个办法精妙的地方便是利用了DENSE_RANK本身会对相同值返回相同的排序号的特点,这点恰恰符合了我们需要DISTINCT的作用。其次,排序号和COUNT的相同之处不就是对记录的个数统计吗?那么取得最大的排序号不就相当于拿到了COUNT的值了吗?确实高明。感叹自己过去怎么就没想到呢?还是很开心可以知道这个办法的。

  • 相关阅读:
    本地安装了flash,前台浏览器还显示需要安装flash?是因为版本需要对应
    关于jsp:include 动态引入的值传递问题(数据共享问题)
    java异常
    理解定义类
    泛型
    SSM配置
    markdown基本语法
    xadmin下设置“use_bootswatch = True”无效的解决办法
    django.db.utils.DataError: (1406, "Data too long for column 'gender' at row 1")
    【转】pycharm使用中的一些快捷键
  • 原文地址:https://www.cnblogs.com/jenrrychen/p/5131410.html
Copyright © 2020-2023  润新知