需要根据城市列明智地安排员工姓名

时间:2016-04-22 21:44:18

标签: sql oracle pivot oracle12c

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

我的查询如下:

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

感谢是否有人可以指导我朝着正确的方向前进。

4 个答案:

答案 0 :(得分:0)

不幸的是,你想要做的事情是不可能的,至少在"直接" SQL - 您需要动态SQL或两步过程(在第一步中生成一个新SQL语句的字符串)。复杂。

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

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

增加:OP在评论中询问后续问题(见下文)。

理想的安排是城市在他们自己的小桌子和城市"在employees表中有一个外键约束,以便" city"事情是可以管理的。您不希望一名HR职员进入纽约,另一名HR职员进入纽约市,第三名进入纽约市进入纽约市。不管怎样,首先尝试代码,方法是在pivot子句中用简单的逗号分隔的字符串文字列表替换跟随运算符IN的子查询:... IN(' DFW' ,' CH',' NY')。请注意,将它们放入此列表的顺序将是输出中列的顺序。我没有检查整个查询,看看是否还有其他问题;试试这个,让我们知道会发生什么。

祝你好运!

答案 1 :(得分:0)

也许您需要转置结果。 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

答案 2 :(得分:0)

选择
(例如城市=" DFW"那么EMPLOYEE_NAME结束)DFW,
(例如城市=" CH"那么EMPLOYEE_NAME结束)CH,
(例如,当城市=" NY"那么EMPLOYEE_NAME结束)NY
来自员工
按first_name订购

答案 3 :(得分:0)

通常我会"编辑"我的第一个答案,但问题已经发生了很大的变化,它与原来的问题有很大的不同,所以我的旧答案不能被编辑和#34; - 现在需要一个全新的答案。

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

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

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

枢轴子句中的

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.