No function exists to perform desired grouping and aggregation - sql

I've run into a conundrum I was hoping someone could help me out with. I have a table with the following fields:
SalesPeriod, SalesRep, Contract, MarginPerProduct, ProductSold
I have to multiply the MarginPerProduct and ProductSold to get 'TotalMargin'
Here is an example of the code I am trying to make work:
SELECT
SalesPeriod
, SalesRep
, Contract
, MarginPerProduct*ProductSold as 'TotalMargin'
FROM
tblSales
GROUP BY
SalesPeriod
, SalesRep
, Contract
Of course, the multiplied columns are invalid because they are not part of the grouping, plus there's no aggregate function being used.
Is there a way to accomplish this type of grouping when using a non recognized aggregation?
Thanks for your help.

Presumably, you want sum():
SELECT SalesPeriod, SalesRep, Contract,
SUM(MarginPerProduct * ProductSold) as TotalMargin
FROM tblSales
GROUP BYSalesPeriod, SalesRep, Contract;

Why not just this
SELECT
SalesPeriod
, SalesRep
, Contract
, TotalMargin = MarginPerProduct*ProductSold
FROM
tblSales
If you want the TotalMargin to be summed up for each SalesPeriod\SalesRep\Contract then
SELECT
SalesPeriod
, SalesRep
, Contract
, TotalMargin = sum(MarginPerProduct*ProductSold)
FROM
tblSales
GROUP BY
SalesPeriod
, SalesRep
, Contract

Related

How to use correct count distinct - Snowflake

I have the below query were I would like to get the number of distinct users who have logged in within a period of a year.
Im trying the below:
select
'Spain' as "COUNTRY"
, 'Snowflake' as "TECHNOLOGY"
, year(event_timestamp) as "YEAR"
, month(event_timestamp) as "MONTH"
, 'USERS_LOGIN' as "KIND"
, distinct count(user_name) as "AMOUNT"
from snowflake.acount_usage.login_history
group by year(event_timestamp), month(event_timestamp);
However, if I try this query I don't get the result I want because the distinct clause and the event_timestamp kind of data seems to not allow this kind of execution.
Does anyone have any advice, please? Thank you in advance.
distinct count(user_name) will just give you one result, the count, the distinct here is irrelevant. if you want a count of distinct usernames change the code to:
select
'Spain' as "COUNTRY"
, 'Snowflake' as "TECHNOLOGY"
, year(event_timestamp) as "YEAR"
, month(event_timestamp) as "MONTH"
, 'USERS_LOGIN' as "KIND"
, count(distinct user_name) as "AMOUNT"
from snowflake.acount_usage.login_history
group by year(event_timestamp), month(event_timestamp);
then the group by will play ball.

Do a Sum and a Difference

I hope someone could guide in the correct path . It's my first class in SQL.
SELECT distinct
a.LICENSEID,
a.license,
a.business_name,
a,year
a.TOTAL_AMOUNT_PAID,
SUM(e.COMPUTED_AMOUNT) over (partition by e.LICENSEID) as AMOUNT_OWNED,
FROM vw_business AS a
INNER JOIN vw_fees AS e ON e.LICENSEID = a.LICENSEID
WHERE LICENSE = '1000'
AND(e.STATUS='BILLED' OR e.STATUS='PAID')
This will give me a result like this:
LICENSEID LICENSE BUSINESS_NAME YEAR TOTAL_AMOUT_PAID AMOUNT_OWNED
1CA6918B 1000 CORTANA 2016 0.00 1000.00
EE6DBDD0 1000 CORTANA 2017 1000.00 1000.00
Basically, I want to add another column to calculate the Total Balance which should be the difference between AMOUNT_OWNED and TOTAL_AMOUNT_PAID. I tried adding another line after SUM like this:
(AMOUNT_OWNED - TOTAL_AMOUNT_PAID) AS TOTAL_BALANCED,
However, I get an error that doesn't recognized the TOTAL_BALANCED. I also tried adding the entire line of the SUM again with no luck.
Can you guys guide in the correct path? If this is possible. Thank you.
Alias names cannot be referred in same select query. You need to write the sum over() window aggregate again to find difference
Try this way
SELECT DISTINCT a.LICENSEID,
a.license,
a.business_name,
a.year, -- Here it is should be . instead of ,
a.TOTAL_AMOUNT_PAID,
Sum(e.COMPUTED_AMOUNT)OVER (partition BY e.LICENSEID) AS AMOUNT_OWNED,
a.TOTAL_AMOUNT_PAID - Sum(e.COMPUTED_AMOUNT)
OVER (
partition BY e.LICENSEID) AS TOTAL_BALANCED
FROM vw_business AS a
INNER JOIN vw_fees AS e
ON e.LICENSEID = a.LICENSEID
WHERE LICENSE = '1000'
AND e.STATUS IN ( 'BILLED', 'PAID' ) -- use IN clause
or use derived table, this is a better option when the expression is big. Query will be more readable
SELECT LICENSEID,
license,
business_name,
year,
TOTAL_AMOUNT_PAID,
AMOUNT_OWNED,
TOTAL_AMOUNT_PAID - AMOUNT_OWNED as TOTAL_BALANCED
FROM (SELECT DISTINCT a.LICENSEID,
a.license,
a.business_name,
a.year,-- Here it is should be . instead of ,
a.TOTAL_AMOUNT_PAID,
Sum(e.COMPUTED_AMOUNT)OVER (partition BY e.LICENSEID) AS AMOUNT_OWNED
FROM vw_business AS a
INNER JOIN vw_fees AS e
ON e.LICENSEID = a.LICENSEID
WHERE LICENSE = '1000'
AND e.STATUS IN ( 'BILLED', 'PAID' ) -- use IN clause
) a

Access Query subtract 2 different column from different row in same table with same ID

I have a table deposit which have column Refund_amt ,Deposit_amt having different Rows with same GR_no . here my question is ,I want to subtract deposit_amt column from Refund_amt
I tried various alternative in query but didn't succeed
My query :
SELECT d.Gr_no
, d.Rec_No
, d.Deposite_Amt
, d.penalty_Amt
, d.Refund_Amt - Refund
, s.Name
, s.cur_std
, cur_div
From
( select d.Refund_Amt refund
from deposite d
, std_gr s
where d.Gr_no = s.Gr_no )
Result would look like this in final total column :
Thank you
You are looking for an aggregation per std_gr: the sum of the deposites minus the sum of the refunds. One way is to do this aggregation in a subquery and join this subquery to your table.
select
d.*, sums.final_total
from deposite d
join
(
select std_gr, nz(sum(deposite_amt),0) - nz(sum(refund_amt),0) as final_total
from deposite
group by std_gr
) as sums on sums.std_gr = d.std_gr
order by d.rec_no;

Make a select with one of the column based on other select

I'm working with windev using the database hyperfile client/serveur.
I have a table named Operation with colums (accountNumber, date, amount, operationType ).
operationType can take two values: "payment" and "withdrawal".
I want to select the List of operations done in an account and, my List should display 5 colums:
Date, accountNumber, amount, operationType and balance.
The last column (balance) should be the difference between the sum of all operations done before the current date with type "payment" and the sum of all operation done before the current date with type "withdrawal"
I try the following sql code
SELECT accountNumber, date as dateOpe, amount, operationType, (SUM (SELECT Operation.amount
FROM Operation
WHERE Operation.date<=dateOpe AND Operation.operationType='payment')
-SUM (SELECT Operation.amount
FROM Operation
WHERE Operation.date<=dateOpe AND Operation.operationType='withdrawal')) as balance
FROM Operation
But I always have an error telling me that i do not have the right to put a select in the SUM
Please can somebody help me. pease how can i write a such sql query.
thanks in advance
Please try this:
SELECT accountNumber, date, amount, operationType,
(SELECT SUM(amount) AS balance
FROM operation WHERE operationType='payment' and date=date)
-(SELECT SUM(amount) AS balance
FROM operation WHERE operationType='withdrawal' and date=date)
as balance
FROM operation
Try something like the following, using a subquery to find the SUMs. There may be a more elegant solution, but this should work.
SELECT date, accountNumber,
operationType, deposits - withdrawals AS balance
FROM Operations o INNER JOIN (
SELECT accountNumber, SUM(amount) AS withdrawals
FROM Operaions
WHERE operationType = 'withdrawal'
GROUP BY accountNumber
) a ON o.accountNumber = a.accountNumber
INNER JOIN (
SELECT accountNumber, SUM(amount) AS deposits
FROM Operations
WHERE operationType = 'deposit'
GROUP BY accountNumber
)b ON o.accountNumber = b.accountNumber
I would use the fact that a logical expression yields 0 if false and 1 if true. Therefore, Operation.amount * <logical expression> will yield 0 if the expression is false and Operation.amount if the expression is true. As a result, the following query should be close to a solution (untested):
SELECT accountNumber, date as dateOpe, amount, operationType,
SUM (Operation.amount * (Operation.date<=dateOpe AND Operation.operationType='payment')) -
SUM (Operation.amount * (Operation.date<=dateOpe AND Operation.operationType='withdrawal')) as balance
FROM Operation

SQL: Using UNION

Here is the question and database info.
Use the UNION command to prepare a full statement for customer 'C001' - it should be laid out as follows. (Note that the values shown below are not correct.) You may be able to use '' or NULL for blank values - if necessary use 0.
Here is a link to the webpage with the database info. http://sqlzoo.net/5_0.htm or see the image below.
Here is what I have tried:
SELECT sdate AS LineDate, "delivery" AS LEGEND, price*quantity AS Total,"" AS Amount
FROM shipped
JOIN product ON (shipped.product=product.id)
WHERE badguy='C001'
UNION
SELECT rdate,notes, "",receipt.amount
FROM receipt
WHERE badguy='C001'
Here is what I get back:
Wrong Answer. The correct answer has 5 row(s).
The amounts don't seem right in the amount column and I can't figure out how to order the data by the date since it is using two different date columns (sdate and rdate which are UNIONED).
Looks like the data in the example is being aggregated by date and charge type using group by, that's why you are getting too many rows.
Also, you can sort by the alias of the column (LineDate) and the order by clause will apply to all the rows in the union.
SELECT sdate AS LineDate, "delivery" AS LEGEND, SUM(price*quantity) AS Total,"" AS Amount
FROM shipped
JOIN product ON (shipped.product=product.id)
WHERE badguy='C001'
GROUP BY sdate
UNION
SELECT rdate, notes, "",receipt.amount
FROM receipt
WHERE badguy='C001'
ORDER BY LineDate
It's usually easiest to develop each part of the union separately. Pay attention to the use of "null" to separate the monetary columns. The first select gets to name the columns.
select s.sdate as tr_date, 'Delivery' as type, sum((s.quantity * p.price)) as extended_price, null as amount
from shipped s
inner join product p on p.id = s.product
where badguy = 'C001'
group by s.sdate
union all
select rdate, notes, null, sum(amount)
from receipt
where badguy = 'C001'
group by rdate, notes
order by tr_date