我想找到一个表的两行之间的差异,并将差值插入同一个表中的第三行。如果第一行值小于第二行,则差异应出现在括号内而不是负符号中。
例如:
Name S1 S2 S3 S4
xxx 98 70 50 85
xxx1 50 90 35 105
Diff 48 (20) 15 (20)
请说是否可以在前端,也就是在gridview中存储值之后。但在Gridview中,colums和rows是Transposed。然后在网格视图中将两列存储的差异存储为第三个新列。
答案 0 :(得分:0)
以下是一些可以执行此操作的代码:
SELECT
Name
,S1
,S2
FROM
(
select
x.Name as xName
,CONVERT(varchar(99), x.S1) as xS1 -- Have to convert everything since you require negatives as ()
,CONVERT(varchar(99), x.S2) as xS2
,1 as xOrder -- To ensure the rows are presented as requested
,x1.Name as x1Name
,CONVERT(varchar(99), x1.S1) as x1S1
,CONVERT(varchar(99), x1.S2) as x1S2
,2 as x1Order
,case
when SIGN(x.S1 - x1.S1) = -1
then '(' + CONVERT(varchar(99), x.S1 - x1.S1) + ')'
else CONVERT(varchar(99), x.S1 - x1.S1)
end as d1
,case
when SIGN(x.S2 - x1.S2) = -1
then '(' + CONVERT(varchar(99), x.S2 - x1.S2) + ')'
else CONVERT(varchar(99), x.S2 - x1.S2)
end as d2
-- etc for S3 and S4
,3 as DiffOrder
from
(select * from dbo.Data where Name = 'xxx') as x
inner join
(select * from dbo.Data where Name = 'xxx1') as x1
on x1.Name = x.Name + '1' -- I suspect your row matching conditin will have
-- to me more sophisticated that this in realit
) as Data
-- The cross apply does an UNPIVOT on the cheap
CROSS APPLY ( VALUES
(xName, xS1, xS2, xOrder),
(x1Name, x1S1, x1S2, x1Order),
('Diff', d1, d2, DiffOrder)
) -- Close paren from the CROSS APPLY
as ca(Name, S1, S2, SortOrder)
order by ca.SortOrder;
让你的表示层执行底片的格式化要好得多。
因为您需要以这种方式呈现的否定,所以列必须是CONVERTed
字符类型。这增加了SQL的复杂性。这也可能意味着他们不再是右对齐的。同样,优秀的演示软件应该能够比SQL更好地为您处理。
我怀疑在你的实际系统中你会有很多行对。你还没有说明与他们匹配的规则是什么。您必须将其添加到代码中。请务必更改排序以解决此问题。
如果您发现布局更易于理解和维护,则可以使用CTE重新格式化代码。
答案 1 :(得分:0)
我不知道你打算如何将varchar插入数字列。我假设s1-s4是数字,因为它们应该是。
你的数据是颠倒过来的,所以最好先将它旋转90度进行计算,然后在结果后再将其旋转显示正确:
declare @t table(Name varchar(4), S1 int, S2 int, S3 int, S4 int)
insert @t values('xxx',98,70,50,85),
('xxx1',50,90,35,105)
--Diff 48 (20) 15 (20)
-- this next part can be put into a view
;with cte as
(
select
sum(case when Name = 'xxx' then Value else -value end) Total, Col
from @t t1
UNPIVOT
(Value FOR Col IN
([S1], [S2], [S3], [S4]) ) AS unpvt
group by col
), cte2 as
(
select case when Total < 0 then
'(' + cast(-Total as varchar(10))+')'
else cast(Total as varchar(10)) end Totalvarchar, Col
from cte
)
select Name,
cast(S1 as varchar(20)) S1, cast(S2 as varchar(20)) S2,
cast(S3 as varchar(20)) S3, cast(S4 as varchar(20)) S4
from @t
union all
select 'Diff' Name, [S1], [S2], [S3], [S4]
from
cte2
PIVOT (max(TotalVarchar) FOR [Col] IN ([S1], [S2], [S3], [S4])) AS pvt
结果:
Name S1 S2 S3 S4
xxx 98 70 50 85
xxx1 50 90 35 105
Diff 48 (20) 15 (20)