【问题标题】:Need to arrange employee names as per their city column wise需要根据城市列明智地安排员工姓名
【发布时间】:2016-04-22 21:44:17
【问题描述】:

我编写了一个查询,它按城市名称从不同的列中提取数据。

我的查询如下:

select q.first_name 
from (select employee_id as eid,first_name,city 
      from employees 
       group by city,first_name,employee_id 
       order by first_name)q
      , employees e 
where e.employee_id = q.eid;

查询的输出是按城市分组的单个列中的员工姓名。

现在我想增强上述查询,以按不同列中的城市名称对员工进行分类。

我尝试使用 pivot 来完成这项工作。这是我的数据透视查询:

select * from ( 
    select q.first_name 
    from (select employee_id as eid,first_name,city 
          from employees 
          group by city,first_name,employee_id  
          order by first_name)q
        , employees e 
       where e.employee_id = q.eid
 ) pivot 
    (for city in (select city from employees))

我遇到一些语法问题,说缺少表达式,我不确定如何使用 pivot 来实现以下预期输出。

预期输出:

DFW                     CH                  NY
----                    ---                 ---
TripeH                  John                Hitman
Batista                 Cena                Yokozuna
Rock                    James               Mysterio

如果有人可以指导我正确的方向,请不胜感激。

【问题讨论】:

    标签: sql oracle pivot oracle12c


    【解决方案1】:

    不幸的是,您尝试做的事情是不可能的,至少在“直接”SQL 中是不可能的——您需要动态 SQL,或两步过程(在第一步中生成一个作为新 SQL 语句的字符串) .复杂。

    问题在于您没有包含固定的城市名称列表(作为字符串文字)。您正在尝试根据您从中获得的任何内容创建列(从员工中选择城市)。因此,在 Oracle 引擎从表中读取数据之前,列数和列名是未知的,但在引擎启动之前,它必须已经知道所有列将是什么。矛盾。

    另请注意,如果可能,您几乎肯定会想要(从员工中选择不同城市)。

    添加:OP 在评论中提出后续问题(见下文)。

    理想的安排是城市在他们自己的较小的表中,并且雇员表中的“城市”具有外键约束,以便“城市”的东西是可管理的。您不希望一名 HR 文员进入纽约,另一名进入纽约市,而第三名进入同一城市的纽约市。一种或另一种方式,首先尝试您的代码,方法是用简单的逗号分隔的城市字符串文字列表替换枢轴子句中运算符 IN 后面的子查询: ... IN ('DFW', 'CH', '纽约')。请注意,您将它们放在此列表中的顺序将是输出中列的顺序。我没有检查整个查询是否还有其他问题;试试这个,让我们知道会发生什么。

    祝你好运!

    【讨论】:

    • 如果我知道列名并且如果我在 ('DFW','CH','NY') 中使用城市,那么如果是的话,我可以得到预期的输出,你能告诉我吗怎么样?
    【解决方案2】:

    选择
    (CITY="DFW" THEN EMPLOYEE_NAME END 时的情况)DFW,
    (CITY="CH" THEN EMPLOYEE_NAME END 时的情况)CH,
    (CITY="NY" THEN EMPLOYEE_NAME END 时的情况)NY
    来自员工
    按名字排序

    【讨论】:

    • 请在发布前根据 OP 的要求测试您的解决方案。
    【解决方案3】:

    也许你需要转置你的结果。 See this link 。我认为 DECODE 或 CASE 最适合您的情况:

    select 
    (CASE WHEN CITY="DFW" THEN EMPLOYEE_NAME END) DFW,
    (CASE WHEN CITY="CH" THEN EMPLOYEE_NAME END) CH,
    (CASE WHEN CITY="NY" THEN EMPLOYEE_NAME END) NY
    FROM employees
    order by first_name
    

    【讨论】:

    • select (CASE WHEN CITY="DFW" THEN EMPLOYEE_NAME END) DFW, (CASE WHEN CITY="CH" THEN EMPLOYEE_NAME END) CH, (CASE WHEN CITY="NY" THEN EMPLOYEE_NAME END) NY FROM 员工按名字排序
    • 您可以编辑您的答案,而不是使用 cmets(或发布另一个答案)。
    • 此解决方案将在每一行的一列中都有一个名称 - 在第一、第二或第三列中 - 在其他两列中为空。不是OP要求的。您在发布之前测试过您的解决方案吗?
    【解决方案4】:

    通常我会“编辑”我的第一个答案,但问题发生了很大变化,与原来的答案大不相同,所以我的旧答案无法“编辑” - 现在需要一个全新的答案。

    您可以通过旋转来做您想做的事情,如下所示。想知道为什么要在基本 SQL 中执行此操作,而不是使用专门为报告需求编写的报告工具。您无需将数据以转置格式保存在数据库中

    您将在芝加哥栏目中看到两次“约克”;你会意识到这是故意的(你会看到我在代码顶部的“测试”表中有一个重复的行);这是为了证明您的安排可能存在缺陷。

    在您询问是否可以获得列表但没有行号之前 - 首先,如果您只是生成一组行,那么这些行是没有排序的。如果您想要为报告目的排序的东西,你可以做我做的,然后从我写的查询中select "'DFW'", "'CHI'", "'NY'"。关系理论和 SQL 标准保证将保留行顺序,但 Oracle 显然确实保留了它,至少在当前版本中是这样;您可以自行承担使用该解决方案的风险。

    对于外行来说,pivot 子句中的

    max(name) 可能看起来很奇怪; Oracle 中 PIVOT 运算符的一个奇怪限制是它需要使用聚合函数,即使它是在一组恰好一个元素上。

    代码如下:

    with t (city, name) as     -- setting up input data for testing
       (
          select 'DFW', 'Smith'     from dual union all
          select 'CHI', 'York'      from dual union all
          select 'DFW', 'Matsumoto' from dual union all
          select 'NY',  'Abu Osman' from dual union all
          select 'DFW', 'Adams'     from dual union all
          select 'CHI', 'Wilson'    from dual union all
          select 'CHI', 'Arenas'    from dual union all
          select 'NY',  'Theodore'  from dual union all
          select 'CHI', 'McGhee'    from dual union all
          select 'NY',  'Zhou'      from dual union all
          select 'NY' , 'Simpson'   from dual union all
          select 'CHI', 'Narayanan' from dual union all
          select 'CHI', 'York'      from dual union all
          select 'NY',  'Perez'     from dual
       )
    select * from
       (
          select row_number() over (partition by city order by name) rn, 
                 city, name 
          from t
       )
    pivot (max(name) for city in ('DFW', 'CHI', 'NY') )
    order by rn
    /
    

    还有输出:

            RN 'DFW'     'CHI'     'NY'
    ---------- --------- --------- ---------
             1 Adams     Arenas    Abu Osman
             2 Matsumoto McGhee    Perez
             3 Smith     Narayanan Simpson
             4           Wilson    Theodore
             5           York      Zhou
             6           York
    
    6 rows selected.
    

    【讨论】:

    • 这符合您的要求吗?
    猜你喜欢
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    • 2017-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-11
    相关资源
    最近更新 更多