【问题标题】:Is it possible to list all possible user's roles with CASE statement from one table? [TERADATA]是否可以使用 CASE 语句从一张表中列出所有可能的用户角色? [Teradata]
【发布时间】:2019-09-30 06:52:06
【问题描述】:

我正在弄清楚是否可以列出用户需要拥有的所有 4 个角色,每个角色都带有“是”或“否”声明。例如。

SELECT DISTINCT Grantee, GranteeKind, RoleName, WhenGranted,
    CASE
        WHEN RoleName='Manager' THEN 'Yes'
        WHEN RoleName='Assistant' THEN 'Yes'
        WHEN RoleName='Executive' THEN 'Yes'
        WHEN RoleName='Deputy' THEN 'Yes'
                    ELSE NULL
            END AS "Already granted?"
    FROM DBC.RolesM
    WHERE Grantee='UserName' 
    AND RoleName IN
    ('Manager',
    'Assistant',
    'Executive',
    'Deputy');

我的查询获取以下结果,它是 100% 正确的。

Grantee    GranteeKind  RoleName    WhenGranted Already Granted? 
UserName    User    Manager         2018-01-30        Yes
UserName    User    Assistant       2016-01-30        Yes

不过,我想知道是否有可能得到这样的东西,所以我们对未分配的角色有明确的答案。

Grantee    GranteeKind  RoleName    WhenGranted Already Granted? 
UserName    User    Manager         2018-01-30        Yes
UserName    User    Assistant       2016-01-30        Yes
UserName    User    Executive       2016-01-30        No
UserName    User    Deputy          2016-01-30        No

【问题讨论】:

    标签: sql database teradata


    【解决方案1】:

    使用cross join 生成行,然后使用left join 引入值。

    不幸的是,Teradata 使生成角色列表有点困难,但这应该可以:

    select g.Grantee, g.GranteeKind, r.RoleName, 
           rm.WhenGranted,
           (case when rm.RoleName is not null then 'Yes' else 'No' end) as already_granted
    from (select distinct grantee, GranteeKind
          from DBC.RolesM
         ) g cross join
         (select distinct RoleName
          from DBC.RolesM
          where RoleName in ('Manager', 'Assistant', 'Executive', 'Deputy')
         ) r left join
         DBC.RolesM rm
         on rm.grantee = g.grantee and rm.rolename = r.rolename
    

    【讨论】:

      【解决方案2】:

      尝试下面给出的查询,希望对您有所帮助。

      SELECT  *
      FROM    ( SELECT  Grantee, GranteeKind, RoleName, WhenGranted, ROW_NUMBER() OVER (PARTITION BY RoleName ORDER BY id) AS RowNumber
          CASE
              WHEN RoleName='Manager' THEN 'Yes'
              WHEN RoleName='Assistant' THEN 'Yes'
              WHEN RoleName='Executive' THEN 'Yes'
              WHEN RoleName='Deputy' THEN 'Yes'
                          ELSE NULL
                  END AS "Already granted?"
          FROM DBC.RolesM
          WHERE Grantee='UserName' 
          AND RoleName IN
          ('Manager',
          'Assistant',
          'Executive',
          'Deputy')) AS a
      WHERE   a.RowNumber = 1

      【讨论】:

      • 感谢您的努力和帮助。正如第二条评论中已经提到的,第一个查询对我来说做得很好。
      • 别担心,小心 OLAP 查询——尤其是对于大型数据集。 ROW_NUMBER() OVER (PARTITION BY ... ORDER BY ...) 可能涉及重新分配,并且绝对涉及排序。如果您为 TPerf(CPU 使用率)付费,除非必须,否则不要执行 OLAP 功能。话虽如此,在这种情况下,它应该不会太糟糕,因为数量会很低。在一个示例中,我对 OLAP 函数进行了基准测试,该函数占用的资源是等效的非 OLAP 函数的 3 倍以上。您应该接受并支持最适合您的答案。
      【解决方案3】:

      我现在无法访问我的 TD,所以我是凭记忆这样做的:

      select Grantee, GranteeKind, RoleName,
          max(managerRole), max(AssistantRole), max(ExecutiveRole), max(DeputyRole)
      from (
        SELECT DISTINCT Grantee, GranteeKind, RoleName, WhenGranted,
          CASE
              WHEN RoleName='Manager' THEN 'Yes' ELSE 'No'
          END as ManagerRole,
          CASE
              WHEN RoleName='Assistant' THEN 'Yes' ELSE 'No'
          END as AssistantRole,
          CASE
              WHEN RoleName='Executive' THEN 'Yes' ELSE 'No'
          END as ExecutiveRole,
          CASE
              WHEN RoleName='Deputy' THEN 'Yes' ELSE 'No'
          END AS DeputyRole
        FROM DBC.RolesM
        WHERE Grantee='UserName' 
          AND RoleName IN
          ('Manager',
          'Assistant',
          'Executive',
          'Deputy')
        ) as DT
      group by 1, 2, 3
      order by 1, 2;
      

      希望不会有语法错误。

      基本上内部查询会产生一个这样的列表:

      Grantee etc, ManagerRole, AssistantRole, etc
      abc,             Yes          No
      abc,             No           Yes
      def,             Yes          No
      def,             No           No
      

      然后外部查询选择每一列的聚合。我们正在做一个最大值,所以“是”将击败“否”。如果用户没有该角色,您只会收到否。

      注意:假设 Grantee、GrantKind 和 RoleName 都相同。如果不是,您将获得每个受赠人的多条记录。我不得不省略“授予时”,因为那可能是在不同的时间。

      【讨论】:

      • 谢谢,这个查询也很有趣,我认为它也可以工作。不过,我发现第一个好一点。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-16
      • 2015-10-29
      相关资源
      最近更新 更多