将行值显示为列标题

时间:2014-02-17 05:55:00

标签: sql oracle plsql oracle10g

我有select声明

SELECT * 
  FROM TABLENAME 
 WHERE WORKERNAME = 'A'
   AND DATE = '12/17/2014'

输出将是:

FREE | USED | DATE      | WORKERNAME
------------------------------------
  1  |  0   |12/17/2014 | A
  1  |  0   |12/17/2014 | A      
  1  |  0   |12/17/2014 | A     

我需要一个输出,其中DATEWORKERNAME的输出将是列标题,如下所示:

    A
----------
12/17/2014
----------
FREE | USED
----------
1    | 0
1    | 0
1    | 0

有人可以建议如何使用oracle SQL或PL / SQL实现这一目标吗?

3 个答案:

答案 0 :(得分:3)

使用纯SQL甚至PL / SQL后生成输出并不是那么优雅。如果让客户做这项工作会更好。根据您希望将最终输出呈现给最终用户的方式,您可以选择从简单的SQL * PLUS到更复杂的报告工具。下面是一个使用SQL * PLUS生成输出的简单示例:

clear screen;

column workername new_value worker_name;
column date1 new_value d1;
column workername noprint;
column date1 noprint;
set linesize 15;
column free format a7;
column used format a7;
ttitle center worker_name skip 1 -
center '------------' skip 1 -
center d1 skip 1 -
center '------------' skip 1;
set colsep '|'

/* sample of data from your question */
with t1(free, used, date1, workername) as(
   select 1, 0, date '2014-12-17', 'A' from dual union all
   select 1, 0, date '2014-12-17', 'A' from dual union all
   select 1, 0, date '2014-12-17', 'A' from dual
)
select to_char(free) as free
     , to_char(used) as used
     , to_char(date1, 'mm/dd/yyyy') as date1
     , workername
  from t1
 where workername = 'A'
   and date1 = date '2014-12-17';

结果:

       A       
  ------------ 
   12/17/2014   
  ------------ 
 FREE   |USED   
 -------|-------
 1      |0      
 1      |0      
 1      |0  

如果需要生成包含不同workernames或/和不同date的报告,则break on SQL * PLUS命令可用于中断特定列的报告或列的组合。例如:

column workername new_value worker_name;
column date1 new_value d1;
column workername noprint;
column date1 noprint;
set linesize 15;
column free format a7;
column used format a7;
ttitle center worker_name skip 1 -
center '------------' skip 1 -
center d1 skip 1 -
center '------------' skip 1;
set colsep '|'
break on worker_name skip page on date1 skip page;

/* sample of data  */
with t1(free, used, date1, workername) as(
   select 1, 0, date '2014-12-17', 'A' from dual union all
   select 1, 0, date '2014-11-17', 'A' from dual union all
   select 1, 0, date '2014-12-17', 'A' from dual union all
   select 1, 0, date '2014-11-17', 'B' from dual
)
select to_char(free) as free
     , to_char(used) as used
     , to_char(date1, 'mm/dd/yyyy') as date1
     , workername
  from t1
 order by workername, date1;

结果:

       A       
  ------------ 
   11/17/2014  
  ------------ 
FREE   |USED   
-------|-------
1      |0      

       A       
  ------------ 
   12/17/2014  
  ------------ 
FREE   |USED   
-------|-------
1      |0      
1      |0      

       B       
  ------------ 
   11/17/2014  
  ------------ 
FREE   |USED   
-------|-------
1      |0      

以下是SQL*PLUS user's guide,您可以在其中找到有关上述示例中使用的任何命令的详细信息。

答案 1 :(得分:0)

TTITLE LEFT 'Manager: ' MGRVAR SKIP 2
BREAK ON MANAGER_ID SKIP PAGE
BTITLE OFF


SELECT MANAGER_ID, DEPARTMENT_ID, LAST_NAME, SALARY
FROM EMP_DETAILS_VIEW
WHERE MANAGER_ID IN (101, 201)
ORDER BY MANAGER_ID, DEPARTMENT_ID;


Manager:       101

DEPARTMENT_ID LAST_NAME                     SALARY
------------- ------------------------- ----------
           10 Whalen                          4400
           40 Mavris                          6500
           70 Baer                           10000
          100 Greenberg                      12000
          110 Higgins                        12000

Manager:       201

DEPARTMENT_ID LAST_NAME                     SALARY
------------- ------------------------- ----------
           20 Fay                             6000

6 rows selected.

看看这样的事情是否对你有帮助。

答案 2 :(得分:0)

使用pivot可能对您有用。

    DECLARE @cols AS NVARCHAR(MAX),
@colsName AS NVARCHAR(MAX),
@query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(WORKERNAME +'_'+convert(varchar(50),[DATE]) +'_'+c.col) 
                  from TRY
                  cross apply 
                  (
                    select 'FREE' col
                    union all
                    select 'USED'
                  ) c
        FOR XML PATH(''), TYPE
        ).value('.', 'NVARCHAR(MAX)') 
    ,1,1,'')
select @colsName 
= STUFF((SELECT distinct ', ' + QUOTENAME(WORKERNAME +'_'+convert(varchar(50),[DATE])+'_'+c.col) 
           +' as ['
           + WORKERNAME + case when c.col = 'FREE' then '_'+convert(varchar(50),[DATE])+'_FREE]' else '_'+convert(varchar(50),[DATE])+'_USED]' end
         from TRY
         cross apply 
         (
            select 'FREE' col
            union all
            select 'USED'

         ) c
        FOR XML PATH(''), TYPE
        ).value('.', 'NVARCHAR(MAX)') 
    ,1,1,'')

set @query = 'SELECT ID, ' + @colsName + ' 
 from 
 (
  select 
    ID, 
    WORKERNAME +''_''+convert(varchar(50),[DATE]) +''_''+col col, 
    value
  from
  (
    select ID, 
      WORKERNAME, 
      date,
    cast(FREE as numeric(10, 2)) FREE,
  cast(USED as numeric(10, 2)) USED
    from TRY
  ) src
  unpivot
  (
    value
    for col in (FREE, USED)
  ) unpiv
 ) s
 pivot 
 (
   sum(value)
   for col in (' + @cols + ')
 ) p 
 order by ID'

execute(@query)