【问题标题】:TSQL Count Over a WindowTSQL 对窗口计数
【发布时间】:2014-12-12 22:38:13
【问题描述】:

找不到我所需要的问题/答案,也找不到示例。我想使用窗口函数。

我有以下架构,其中包含存储的过程以及这些过程中使用的表和列:

CREATE TABLE [dbo].[ProcedureDependencies](
[DatabaseName] [varchar](256) NOT NULL,
[ProcedureId] [int] NOT NULL,
[ProcedureSchemaName] [varchar](256) NOT NULL,
[ProcedureName] [varchar](256) NOT NULL,
[TableSchemaName] [varchar](256) NOT NULL,
[TableName] [varchar](256) NOT NULL,
[FieldName] [varchar](256) NOT NULL)

我想计算一个表名出现在不同过程中的次数。

我一直在尝试以下变体:

select 
    DatabaseName,
    TableName, 
    count(tablename) over (partition by DatabaseName,ProcedureName) cnt
from ProcedureDependencies
order by cnt desc

但是,我得到了不好的结果。例如,在我想要的下面的脚本中......

databasename    tablename    cnt
db1             tbl1         3
db1             tbl2         1
db1             tbl3         1

但我得到了....

databasename    tablename    cnt
db1             tbl1         3
db1             tbl2         3
db1             tbl3         3
db1             tbl1         1

脚本:

drop table #tmprmd;
create table #tmprmd (
    DatabaseName varchar(max),
    TableName varchar(max), 
    ProcedureName varchar(max), 
    FieldName varchar(max));
Insert Into #tmprmd
Values  ('db1',     'tbl1',     'proc1',    'field1'),
        ('db1',     'tbl1',     'proc1',    'field2'),
        ('db1',     'tbl2',     'proc1',    'field1'),
        ('db1',     'tbl1',     'proc2',    'field1'),
        ('db1',     'tbl3',     'proc1',    'field1'),
        ('db1',     'tbl1',     'proc3',    'field1');
with 
dist as (
    select 
        --distinct
        databasename,
        procedurename,
        tablename
    from #tmprmd--ProcedureDependencies
)
select 
distinct
    DatabaseName,
    TableName, 
    count(tablename) over (partition by DatabaseName,procedurename) cnt
from dist
order by cnt desc

【问题讨论】:

  • 在想要的结果中不应该是 4,1,1 吗?
  • @米海不行,必须是3,1,1

标签: tsql window-functions


【解决方案1】:

我认为你做的比它需要的更难

drop table #tmprmd;
create table #tmprmd (
    DatabaseName varchar(max),
    TableName varchar(max), 
    ProcedureName varchar(max), 
    FieldName varchar(max));
Insert Into #tmprmd
Values  ('db1',     'tbl1',     'proc1',    'field1'),
        ('db1',     'tbl1',     'proc1',    'field2'),
        ('db1',     'tbl2',     'proc1',    'field1'),
        ('db1',     'tbl3',     'proc1',    'field1'),
        ('db1',     'tbl1',     'proc2',    'field1'),       
        ('db1',     'tbl1',     'proc3',    'field1');
select dist.DatabaseName, dist.TableName, count(distinct(procedurename)) 
from #tmprmd as dist  
group by dist.DatabaseName, dist.TableNameName

【讨论】:

    【解决方案2】:
            IF OBJECT_ID('Tempdb..#tmprmd') IS NOT NULL 
                DROP TABLE #tmprmd
            CREATE TABLE #tmprmd
                (
                  DatabaseName VARCHAR(MAX) ,
                  TableName VARCHAR(MAX) ,
                  ProcedureName VARCHAR(MAX) ,
                  FieldName VARCHAR(MAX)
                );
            INSERT  INTO #tmprmd
            VALUES  ( 'db1', 'tbl1', 'proc1', 'field1' ),
                    ( 'db1', 'tbl1', 'proc1', 'field2' ),
                    ( 'db1', 'tbl2', 'proc1', 'field1' ),
                    ( 'db1', 'tbl1', 'proc2', 'field1' ),
                    ( 'db1', 'tbl3', 'proc1', 'field1' ),
                    ( 'db1', 'tbl1', 'proc3', 'field1' );
    ----------------------------------------------------------
        -- variant 1
            WITH    cte
                      AS ( SELECT DISTINCT
                                    T.DatabaseName ,
                                    T.TableName ,
                                    COUNT(*) OVER ( PARTITION BY T.DatabaseName, T.ProcedureName, T.TableName ) cnt
                           FROM     #tmprmd AS T
                         )
                SELECT  DISTINCT
                        DatabaseName ,
                        TableName ,
                        SUM(cte.cnt) OVER ( PARTITION BY DatabaseName, TableName ) cnt
                FROM    cte
    ----------------------------------------------------------
        --variant 2
        SELECT DISTINCT dist.DatabaseName,
                        dist.TableName,
                        MAX(cnt) OVER (PARTITION BY dist.DatabaseName, dist.TableName) cnt
        FROM (  SELECT DISTINCT T.DatabaseName,
                                T.TableName,
                                DENSE_RANK() OVER (PARTITION BY T.TableName order by T.ProcedureName ) cnt
                FROM #tmprmd AS T
             ) dist
    ----------------------------------------------------------
        --variant 3
        SELECT DISTINCT dist.DatabaseName,
                        dist.TableName,
                        COUNT(cnt) OVER (PARTITION BY dist.DatabaseName, dist.TableName) cnt
        FROM (  SELECT DISTINCT T.DatabaseName,
                                T.TableName,
                                DENSE_RANK() OVER (PARTITION BY T.TableName order by T.ProcedureName ) cnt
                FROM #tmprmd AS T
             ) dist
    ----------------------------------------------------------
        -- Variant 4, without using window function
        SELECT T.DatabaseName,
               T.TableName,
               COUNT(DISTINCT T.ProcedureName ) cnt
        FROM #tmprmd AS T
        GROUP BY T.DatabaseName,T.TableName
    

    【讨论】:

    • 变体 4 是我在您编辑前 13 小时发布的答案。你偷看了吗?
    • @Blam,是的,之前的支持,如果你有异议,我可以从我的帖子中删除它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-20
    • 1970-01-01
    • 2021-11-10
    • 1970-01-01
    • 2018-12-08
    • 2018-12-09
    • 2021-05-12
    相关资源
    最近更新 更多