Sum Column Based on Other Columns with Similar Data - sql

Trying to write a SQL query that would sum values based on another columns data. The part that have me stomped is the fact that the other column's data is partially alike as seen below.
AccountID AcctName Amount
---------------------------------------
1-1-100-2 Vehicles 10000
1-1-100-3 Vehicles 20000
1-1-100-4 Vehicles 20000
1-2-500-1 Books 10000
1-2-600-1 Pencils 500
I'd like to have this data display as:
AccountID AcctName Amount
--------------------------------------
1-1-100 Vehicles 50000
1-2-500 Books 10000
1-2-600 Pencils 500

Assuming the significant part of AccountId is always the first 7 characters, you can try with:
SELECT
SUBSTRING(AccountID,0,7),
AcctName,
SUM(Amount)
FROM YourTable
GROUP BY AcctName, SUBSTRING(AccountID,0,7)

Group by AcctName, left(AccountID, 7)

Related

Possible to keep fraction in a query?

I am looking for a way to add up averages in SQL. Here is an example of the data I have:
product avg_price
phone 104.28
car 1000.00
And I'm looking to build something like this:
product avg_price
[all] 544.27
phone 104.28
car 1000.00
The way I'm currently doing it is to store the count and sum in two different columns, such as:
product cnt total
phone 203 20,304.32
car 404 304,323.30
And from that get the average. However, I was wondering if it is possible in SQL to just 'keep the fraction' and be able to add them as needed. For example:
product avg_price
[all] [add the fractions]
phone 20,304.32 / 203
car 304,323.30 / 404
Or do I need to use two columns in order to get an average of multiple aggregated rows?
You don't need 2 columns to get the average, but if you want to display as a fraction then you will need both numbers. They don't need to be in 2 columns though.
select product, sum(total) ||'/'||sum(count)
from table a
join table b on a.product=b.product
union
select product, total ||'/'||count
from table a
join table b on a.product=b.product;

select * columns but group by two specific columns in sql

In the tab above you can see several records in some cases the Material column of the record n ​​is equal to the record n ​​+ 1 and in the Material column Desc the record n ​​is equal to the record n ​​+ 1.
But it does not make the columns List Price USD and RVS-ZSEG what happens is that I need to make a group by or combine the pairs in some registers but that they become complementary.
For example that in register
1 and 2 would be converted by combining the values ​​of List Price USD and RVS ZSEG should be shown as image below
Try this:
SELECT Material, MaterialDesc
,MAX([D-Chain-Spec(Status)])[D-Chain-Spec(Status)]
,MAX([List Price USD])[List Price USD]
,MAX([RVS - ZSEG])[RVS - ZSEG]
FROM YourTable
GROUP BY Material, MaterialDesc
From what I see you just need a sum on List Price USD and RVS-ZSEG right?
SELECT Material, MaterialDesc,[D-Chain-Spec(Status)]
,SUM([List Price USD]) as [List Price USD]
,SUM([RVS - ZSEG]) as [RVS - ZSEG]
FROM Table
GROUP BY Material, MaterialDesc,[D-Chain-Spec(Status)]

Total Sum SQL Server

I have a query that collects many different columns, and I want to include a column that sums the price of every component in an order. Right now, I already have a column that simply shows the price of every component of an order, but I am not sure how to create this new column.
I would think that the code would go something like this, but I am not really clear on what an aggregate function is or why I get an error regarding the aggregate function when I try to run this code.
SELECT ID, Location, Price, (SUM(PriceDescription) FROM table GROUP BY ID WHERE PriceDescription LIKE 'Cost.%' AS Summary)
FROM table
When I say each component, I mean that every ID I have has many different items that make up the general price. I only want to find out how much money I spend on my supplies that I need for my pressure washers which is why I said `Where PriceDescription LIKE 'Cost.%'
To further explain, I have receipts of every customer I've worked with and in these receipts I write down my cost for the soap that I use and the tools for the pressure washer that I rent. I label all of these with 'Cost.' so it looks like (Cost.Water), (Cost.Soap), (Cost.Gas), (Cost.Tools) and I would like it so for Order 1 it there's a column that sums all the Cost._ prices for the order and for Order 2 it sums all the Cost._ prices for that order. I should also mention that each Order does not have the same number of Costs (sometimes when I use my power washer I might not have to buy gas and occasionally soap).
I hope this makes sense, if not please let me know how I can explain further.
`ID Location Price PriceDescription
1 Park 10 Cost.Water
1 Park 8 Cost.Gas
1 Park 11 Cost.Soap
2 Tom 20 Cost.Water
2 Tom 6 Cost.Soap
3 Matt 15 Cost.Tools
3 Matt 15 Cost.Gas
3 Matt 21 Cost.Tools
4 College 32 Cost.Gas
4 College 22 Cost.Water
4 College 11 Cost.Tools`
I would like for my query to create a column like such
`ID Location Price Summary
1 Park 10 29
1 Park 8
1 Park 11
2 Tom 20 26
2 Tom 6
3 Matt 15 51
3 Matt 15
3 Matt 21
4 College 32 65
4 College 22
4 College 11 `
But if the 'Summary' was printed on every line instead of just at the top one, that would be okay too.
You just require sum(Price) over(Partition by Location) will give total sum as below:
SELECT ID, Location, Price, SUM(Price) over(Partition by Location) AS Summed_Price
FROM yourtable
WHERE PriceDescription LIKE 'Cost.%'
First, if your Price column really contains values that match 'Cost.%', then you can not apply SUM() over it. SUM() expects a number (e.g. INT, FLOAT, REAL or DECIMAL). If it is text then you need to explicitly convert it to a number by adding a CAST or CONVERT clause inside the SUM() call.
Second, your query syntax is wrong: you need GROUP BY, and the SELECT fields are not specified correctly. And you want to SUM() the Price field, not the PriceDescription field (which you can't even sum as I explained)
Assuming that Price is numeric (see my first remark), then this is how it can be done:
SELECT ID
, Location
, Price
, (SELECT SUM(Price)
FROM table
WHERE ID = T1.ID AND Location = T1.Location
) AS Summed_Price
FROM table AS T1
to get exact result like posted in question
Select
T.ID,
T.Location,
T.Price,
CASE WHEN (R) = 1 then RN ELSE NULL END Summary
from (
select
ID,
Location,
Price ,
SUM(Price)OVER(PARTITION BY Location)RN,
ROW_number()OVER(PARTITION BY Location ORDER BY ID )R
from Table
)T
order by T.ID

How to make one column fixed?

There is one scheme and different items inside it, so the scenario is that if user send SchemeID to the procedure then it should return the SchemeName(once) and all items inside a scheme i.e. DescriptionOfitem, Quantity, Rate, Amount... in this format
SchemeName DescriptionOfItems Quantity Unit Rate Amount
Scheme01 Bulbs 2 M2 200 400
Titles 10 M3 300 3000
SolarPanels 2 M2 1000 2000
Bricks 50 M9 50 2500
Total 7900
My try, it works but it also repeats the SchemeName for each row and can't find total
Select
Schemes.SchemeName,
ContractorsWorkDetails.ContractorsWorkDetailsItemDescription,
ContractorsWorkDetails.ContractorsWorkDetailsUnit,
ContractorsWorkDetails.ContractorsWorkDetailsItemQuantity,
ontractorsWorkDetails.ContractorsWorkDetailsItemRate,
ContractorsWorkDetails.ContractorsWorkDetailsAmount
From ContractorsWorkDetails
Inner Join Schemes
ON Schemes.pk_Schemes_SchemeID= ContractorsWorkDetails.fk_Schemes_ContractorsWorkDetails_SchemeID
Where ContractorsWorkDetails.fk_Schemes_ContractorsWorkDetails_SchemeID= 2
Update:
I tested the query as suggested below but it gives this kinda result
You can get the total using grouping sets. I would advise you to keep the schema name on each row. If you want it filtered out on certain rows, then do that at the application layer.
Now, having said that, I think this will do what you want in SQL:
Select (case when GROUPING(cwd.ContractorsWorkDetailsItemDescription) = 0
then 'Total'
when row_number() over (partition by s.SchemeName
order by cwd.ContractorsWorkDetailsItemDescription
) = 1
then s.SchemeName else ''
end) as SchemeName,
cwd.ContractorsWorkDetailsItemDescription,
cwd.ContractorsWorkDetailsUnit,
cwd.ContractorsWorkDetailsItemQuantity,
cwd.ContractorsWorkDetailsItemRate,
SUM(cwd.ContractorsWorkDetailsAmount) as ContractorsWorkDetailsAmount
From ContractorsWorkDetails cwd Inner Join
Schemes s
ON s.pk_Schemes_SchemeID = cwd.fk_Schemes_ContractorsWorkDetails_SchemeID
Where cwd.fk_Schemes_ContractorsWorkDetails_SchemeID = 2
group by GROUPING SETS ((s.SchemeName,
cwd.ContractorsWorkDetailsItemDescription,
cwd.ContractorsWorkDetailsUnit,
cwd.ContractorsWorkDetailsItemQuantity,
cwd.ContractorsWorkDetailsItemRate
), s.SchemeName)
Order By GROUPING(cwd.ContractorsWorkDetailsItemDescription),
s.SchemeName, cwd.ContractorsWorkDetailsItemDescription;
The reason you don't want to do this in SQL is because the result set no longer has a relational structure: the ordering of the rows is important.

SQL query for child table summary and generalazation

I have 4 tables with diagram below
I want to summary query for the Institution table. where I want to get result of only,
InstitutionType ProductName Quantity
For example. sample data of institution table
Id Name Address InstitionTypeId
1 aaa ny132 1001
2 bbb dx23 1001
3 ccc bn33 1002
And the InstitionProduct is like that
Id ProductId Quantity InstitionId
1 1000 120 1
2 1000 100 2
3 1000 50 3
Then I want a query result to output total quantity of a given product by Instition Type wise. The sample output will look like this.
InstitutionTypeId productId quantity
1001 1000 220
1002 1000 50
So I want to group the institution by type and aggregate the product quantity of all institution type group.
I tried to use the group by clause, but with the product quantity not as a grouping element it results in error.
SELECT
Institution.InstitutionTypeID,
InstitutionProduct.ProductID,
SUM(InstitutionProduct.Quantity)
FROM
Institution
LEFT JOIN
InstitutionProduct
ON InstitutionProduct.InstitutionID = Institution.ID
GROUP BY
Institution.InstitutionTypeID,
InstitutionProduct.ProductID
If you are querying with group by you need to use either aggregate functions or group by all included fields. The reason is, that the 'group by' returns exactly one row per 'group by' value, so if you introduce an ungrouped field, this would conflict if the field has more than one value per grouping constraint. Even though this might not be the case for your dataset, the query engine cannot know this, and raises an error.
The solution is to introduce aggregates for all non-grouping field with aggregates being (among others): average (avg), summarize (sum), minimum (min) and maximum (max). This would lead to something like
SELECT i.InstitutionTypeID, i.Institution.ID, SUM(ip.Quantity)
FROM Institution I LEFT JOIN InstitutionProduct IP
ON IP.InstituationID = I.ID
GROUP BY i.InstitutionTypeID, i.Institution.ID