合并SQL中的公共行

合并SQL中的公共行,sql,oracle,Sql,Oracle,我得到以下输出 Code Manager Employee 1 A Emp1 1 A Emp2 1 A Emp3 2 B Emp4 2 B Emp5 但我想要结果 Code Manager Employee 1 A Emp1 Emp2

我得到以下输出

Code  Manager    Employee
1      A          Emp1
1      A          Emp2   
1      A          Emp3  
2      B          Emp4
2      B          Emp5
但我想要结果

Code   Manager    Employee
1       A          Emp1
                   Emp2
                   Emp3
2       B          Emp4
                   Emp5

代码列和管理器列不应重复。它应为空。

这是SQL无法做到的。您应该在从数据库接收数据后手动在代码中循环数据

编辑


在Vashh和Lieven的评论之后,我意识到这是可能的。因此,如果他需要显示,他可以使用Vaassh建议的Func,使用null s连接。由Lieven或可能是循环并添加到datagridview或表或任何他想要使用的内容。

您需要Access或Crystal Reports之类的东西来进行这种格式化。这在普通SQL中是不可能的。

为了好玩,下面是一种方法,但最终,在最终用户应用程序中做得更好

;WITH YourTable (Code, Manager, Employee) AS(
    SELECT * FROM (VALUES 
        (1, 'A', 'Emp1')
        , (1, 'A', 'Emp2')
        , (1, 'A', 'Emp3')
        , (2, 'B', 'Emp4')
        , (2, 'B', 'Emp5')
    ) a (b, c, d)       
)
, q AS (
    SELECT  rn = ROW_NUMBER() OVER (ORDER BY Code, Manager, Employee), *
    FROM    YourTable
)
SELECT  Code = CASE WHEN q1.Code = q2.Code THEN NULL ELSE q1.Code END
        , Manager = CASE WHEN q1.Code = q2.Code THEN NULL ELSE q1.Manager END
        , q1.Employee
FROM    q q1
        LEFT OUTER JOIN q q2 ON q1.rn = q2.rn + 1

我知道您在Oracle中寻求答案,但如果您真的需要这样做,而不是在报告环境中,则此SQL Server示例可能会对您有所帮助:

DECLARE @TBL TABLE(
  Code     INT,
  Manager  CHAR(1),
  Employee VARCHAR(4))

INSERT @TBL VALUES (1,'A','Emp1')
INSERT @TBL VALUES (1,'A','Emp2')
INSERT @TBL VALUES (1,'A','Emp3')
INSERT @TBL VALUES (2,'B','Emp4')
INSERT @TBL VALUES (2,'B','Emp5')

;WITH cte
     AS (SELECT Code
                ,Manager
                ,Employee
                ,ROW_NUMBER() OVER(ORDER BY Code) rownum
         FROM   @TBL)
SELECT CASE curr.Code
         WHEN prev.Code THEN ''
         ELSE CAST(curr.Code AS VARCHAR(20))
       END AS _Code
       ,CASE curr.Manager
          WHEN prev.Manager THEN ''
          ELSE curr.Manager
        END AS _Manager
       ,curr.Employee
FROM   cte curr
       LEFT JOIN cte prev
         ON curr.rownum = prev.rownum + 1

如果您只是使用SQLServer2005/2008,那么可以通过以下方法实现这一点

declare @table table (
Code int,
Manager Varchar(1),
Employee varchar(10)
)

insert into @table values
(1,'A','Emp1'),
(1,'A','Emp2'),
(1,'A','Emp3'),
(2,'A','Emp4'),
(2,'A','Emp5')

select * from @table
select
case when number=1 then Code else null end as Code,
case when number=1 then Manager else null end as Manager,
employee
from (
select *,
row_number() over (partition by code, manager order by code,manager) as number
from @table
) x
这将给你:

(5 row(s) affected)
Code        Manager Employee
----------- ------- ----------
1           A       Emp1
1           A       Emp2
1           A       Emp3
2           A       Emp4
2           A       Emp5

(5 row(s) affected)

Code        Manager employee
----------- ------- ----------
1           A       Emp1
NULL        NULL    Emp2
NULL        NULL    Emp3
2           A       Emp4
NULL        NULL    Emp5

(5 row(s) affected)
完成:

如果愿意,可以将空值更改为

WITH 
CTE1 AS (
SELECT DISTINCT [Code], [Manager], 
(   SELECT TOP 1 Employee 
    FROM [dbo].[table] t2 
    WHERE t1.Code = t2.Code AND t1.Manager = t2.Manager 
    ORDER BY Employee) AS [Employee]
FROM [dbo].[table] t1)
,
CTE2 AS (
        SELECT * FROM [dbo].[table]
        EXCEPT
        SELECT * FROM CTE1)

SELECT * FROM CTE1
UNION
SELECT NULL as Code, NULL as Manager, Employee
FROM CTE2
ORDER BY Employee

试试看

我的SQL*Plus有点生锈,但如果您使用的是这个工具,那么它应该相当简单,但是使用BREAK命令

正如一篇关于的评论中提到的,这最好留给您的报告工具,而不是在实际的SQL中执行,因为没有所有值的单行在结果集的上下文之外没有任何意义

BREAK on code on manager

SELECT code, manager, employee
FROM yourTable y
order by code, manager;

请注意,我的SQL*Plus有点生疏,因此这可能无法正常工作,但可以找到BREAK命令的详细信息。

我认为您无法通过查询实现这一点……您真的确定这有意义吗?请解释您的上下文/您为什么要这样做如果您将列留空,您如何判断Emp2代表Code=1和Manager=A?我很确定,作者需要这样的SRTAGE输出来生成特定的用户界面。在这种情况下,保留第一个结果集并在客户机代码中实现显示逻辑是有意义的。结果不是一种关系,例如行顺序,因此它不是最适合SQL的。我建议您使用报表编写工具来执行这种格式设置。您可以使用transact-sql函数来执行此操作,但在逻辑上似乎不正确—这是可能的,但并不完美。它将涉及连接自身,并使用case语句来确定代码和管理器是应该输出它们的值还是只输出NULL。是的,我完全忘记了这一点。我想如果他只是为了更好的显示,他可以按照你们的建议选择func或join。没有看到Oracle标签:-
BREAK on code on manager

SELECT code, manager, employee
FROM yourTable y
order by code, manager;