zoukankan      html  css  js  c++  java
  • 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的值了吗?确实高明。感叹自己过去怎么就没想到呢?还是很开心可以知道这个办法的。

  • 相关阅读:
    八枚硬币问题
    找出诡异的Bug:数据怎么存不进去
    IKAnalyzer使用停用词词典进行分词
    【Quick-COCOS2D-X 3.3 怎样绑定自己定义类至Lua之四】使用绑定C++至Lua的自己定义类
    iOS 自我检測
    蓝桥杯 BASIC 29 高精度加法(大数)
    二叉树的非递归遍历
    [算法]有趣算法合辑[11-20]
    习惯的力量之四理直气壮的借口?
    《github一天一道算法题》:分治法求数组最大连续子序列和
  • 原文地址:https://www.cnblogs.com/jenrrychen/p/5131410.html
Copyright © 2011-2022 走看看