Reputation: 23
I have a table that stores information in the below format.
id, value , property are the columns. I have a requirement now to sum up data based on property.
i.e for property column F2 and Value,
I need values summed up and displayed as below:
Type | Sum
Cars | 1892+702+515
Bikes | 1393 +0 + 474.6
Note: I know this is not the way to store data in a table, but table alterations are currently not possible.
Appreciate if you could give your inputs on this.
Upvotes: 0
Views: 404
Reputation: 1271003
This looks like a really bad design. It looks like you are using the positions in the table to assign "groupings". Fortunately, you have an id
column, so this is possible to do in SQL.
Here is the idea: First assign the appropriate F2
property to each row. Then do an aggregation. This following uses outer apply
for the first part and group by
for the second:
select t2.value,
sum(case when isnumeric(t.value) = 1 then cast(t.value as decimal(10, 2))
end) as thesum
from t outer apply
(select top 1 t2.*
from t t2
where t2.id <= t.id and t2.property = 'F2'
order by t2.id desc
) t2
group by t2.value;
This doesn't filter out the first group (all 0's). You can do that with an additional WHERE
clause if you like.
Upvotes: 1
Reputation: 7928
Here's another solution which uses LEAD in case if you are running SQL Server 2012+ (note my comments).
-- Sample data
DECLARE @yourtable
TABLE
(
id int identity primary key, -- emulate an index on ID
value varchar(100),
property varchar(5)
);
INSERT @yourtable (value, property) VALUES
('0', 'F2'),
('0', 'V1'),
('0', 'V2'),
('0', 'V3'),
('Cars', 'F2'),
('1892', 'V1'),
('702', 'V2'),
('515', 'V3'),
('Bikes', 'F2'),
('1393', 'V1'),
('0', 'V2'),
('474.6', 'V2');
-- Solution
WITH startPoints AS
(
SELECT *, rn = ROW_NUMBER() OVER (ORDER BY id)
FROM @yourtable
),
groups AS
(
SELECT value, rn, ttl =
ISNULL(LEAD(id,1) OVER (ORDER BY id), (SELECT COUNT(*) FROM @yourtable)+1) - (rn+1)
FROM startPoints
WHERE property = 'F2' AND value LIKE ('%[^0-9.]%')
)
SELECT
value,
SUM =
(
SELECT SUM(CAST(value AS decimal(10,2)))
FROM startPoints s
WHERE s.rn BETWEEN g.rn+1 AND g.rn+ttl
)
FROM groups g;
Upvotes: 1