TSQL Aggregating values based on other column - sql-server

I have a table that looks as follows
Amount Factor Month Customer
1 1 2 A
3 1 2 A
4 -1 2 A
2 1 2 B
2 1 2 B
3 -1 2 B
4 1 3 A
5 1 3 A
6 -1 3 A
I want to aggregate (sum) the column Amount per Month and Customer. The Amounts should be multiplied with the value in the column Factor.
Hence, the result should look as follows (could be an UPDATE to the same table or a new table):
Amount Factor Month Customer
0 1 2 A
1 1 2 B
3 1 3 A

Try below
SELECT SUM(Amount * Factor) as Amount,Month,Customer
FROM tableName
GROUP BY Month,Customer

I think this is what you want:
select month, customer, sum(amount * factor) as sum_amount
from t
group by month, customer;
I'm not sure why you would want factor in the result set.

Related

Count number of rows for each id to create a new column

ID
value
1
4
1
5
3
4
2
10
I want to add another column called count, that has for each id the number of observations.
Transformed table
id
value
count
1
4
2
1
5
2
3
4
1
2
10
1
You can use the OVER() clause to aggregate.
SELECT
ID,
value,
[count] = COUNT(*) OVER (PARTITION BY ID)
FROM dbo.TableName;

Classifying rows into a grouping column that shows the data is related to prior rows

I have a set of data that I want to classify into groups based on a prior record id existing on the newer rows. The initial record of the group has a prior sequence id = 0.
The data is as follows:
customer id
sequence id
prior_sequence id
1
1
0
1
2
1
1
3
2
2
4
0
2
5
4
2
6
0
2
7
6
Ideally, I would like to create the following grouping column and yield the following results:
customer id
sequence id
prior sequence id
grouping
1
1
0
1
1
2
1
1
1
3
2
1
2
4
0
2
2
5
4
2
2
6
0
3
2
7
6
3
I've attempted to utilize island gap logic utilizing the ROW_NUMBER() function. However, I have been unsuccessful in doing so. I suspect the need here is more along the lines of a recursive CTE, which I am attempting at the moment.
I agree that a recursive CTE will do the job. Something like:
WITH reccte AS
(
/*query that determines starting point for recursion
*
* In this case we want all records with no prior_sequence_id
*/
SELECT
customer_id,
sequence_id,
prior_sequence_id,
/*establish grouping*/
ROW_NUMBER() OVER (ORDER BY sequence_id) as grouping
FROM yourtable
WHERE prior_sequence_id = 0
UNION
/*join the recursive CTe back to the table and iterate*/
SELECT
yourtable.customer_id,
yourtable.sequence_id,
yourtable.prior_sequence_id,
reccte.grouping
FROM reccte
INNER JOIN yourtable ON reccte.sequence_id = yourtable.prior_sequence_id
)
SELECT * FROM reccte;
It looks like you could use a simple correlated query, at least given your sample data:
select *, (
select Sum(Iif(prior_sequence_id = 0, 1, 0))
from t t2
where t2.sequence_id <= t.sequence_id
) Grouping
from t;
See Example Fiddle

Move a specific column for every rows of a group from a result set into a single row

I tried using pivot in SQL Server, but I'm just going in circles with no good results.
I have this result set that could vary in number of records:
ForeignID
Name
Value
1
A
1
1
B
2
1
C
3
2
D
4
How can I do a SELECT to get this for all rows with ForeignID of 1:
ForeignID
A
B
C
1
1
2
3

SQL Server sum column base on id

I have table and I want result like this:
id ItemId Quantity Sum
1 1 2 2
2 1 1 3
3 1 1 4
4 2 3 3
4 2 1 4
5 3 6 6
where id is primary key and ItemId is foreign key and Quantity is integer column.
I want that "sum" column sum quantity base on itemId.
I used group by but it does not give me what I want. With group by
I get this result:
id ItemId Quantity Sum
1 1 2 4
2 1 1 4
3 1 1 4
. . . .
. . . .
The "sum" column is same for all related rows.
I also used this code:
select it1.id, it1.ItemId, it1.Quantity ,
(select sum(it2.Quantity) from InventoryTransactions it2 where it2.ItemId = it1.ItemId and it2.id <= it1.Id) as Sum
from InventoryTransactions it1
order by it1.ItemId , it1.Id
This code gives me what I want but it takes too long for a large number of records, for example for one million records. It takes more than two minute to execute
What is the best way?
In sql server >= 2012 you can do a rolling sum easier
select it1.id, it1.ItemId, it1.Quantity,
sum(Quantity) over(partition by itemid order by Id rows unbounded preceding) as Sum
from InventoryTransactions it1
order by it1.ItemId , it1.Id

Computing a field to identify chronological order of datapoints that share the same ID

I using Microsoft SQL Server 2008 to try and identify the chronological order of data points in order to create a filter field that will allow me to create a query that only includes the first and last record for each ID number, where multiple rows represent different data points from the same ID
Here is an example of my current data and desired data to give a better idea of what I mean:
Current Data
ID Indicator Date
1 1 1988-02-11
1 1 1989-03-9
1 1 1993-04-3
1 1 2001-05-4
2 1 2000-01-01
2 1 2001-02-03
2 1 2002-04-22
3 1 1990-02-01
3 1 1998-02-01
3 1 1999-03-02
3 1 2000-04-02
4 0 NA
Desired Data
ID Indicator Date Order_Indicator
1 1 1988-02-11 1
1 1 1989-03-9 2
1 1 1993-04-3 3
1 1 2001-05-4 4
2 1 2000-01-01 1
2 1 2001-02-03 2
2 1 2002-04-22 3
3 1 1990-02-01 1
3 1 1998-02-01 2
3 1 1999-03-02 3
3 1 2000-04-02 4
4 0 NULL NULL
The field I want to create is the "Order_Indicator" field in the "Desired Data" table and with the only relevant records are records with Indicator = 1. With this information I would create a query where I only select the rows where Order_Indicator = 1 and Order_Indicator = MAX(Order_Indicator) for each "row group" that share the same ID. Does anyone have any idea about how I might go about this? I know I could do this very easily in Excel but I need to do it on SQL server in order for it to be reproducible with my colleagues.
Thank you so much in advance!
You can do this with the ranking functions:
select c.*,
(case when indicator = 1
then row_number() over (partition by id, indicator order by [date])
end) as OrderIndicator
from current c
This assigns a sequential number based on the date and indicator. The case statement takes care of the indicator = 0 case.
By the way, this assumes that "date" is being stored as a date.
Use below query :
select YourTable.ID,
YourTable.indicator,
case when date<>'NA' then date end as date,
case when indicator = 1 then row_number() over (partition by id, indicator order by ID) end as Order_Indicator
from YourTable

Resources