合并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;