Sum two results from SQL query - sql

I just started learning SQL. I filtered the data I have and accordingly two results came out. I want to collect these results, but whatever I do, it throws an error.
Here is my code:
SELECT TOP (1000) [Sec_id]
,[Prc_date]
,[Mkt_Price]
,[Currency]
,[Pricing_factor]
FROM [EXAMPLE1].[dbo].[market]
WHERE Currency='INR' OR Currency='AUD';
SELECT SUM(Mkt_Price)* Pricing_factor as INR FROM market
where Currency='INR' and Mkt_Price>100 group by Pricing_factor ;
SELECT SUM(Mkt_Price)* Pricing_factor as AUD FROM market
where Currency='AUD' and Mkt_Price>100 group by Pricing_factor ;
SELECT SUM(Mkt_Price)* Pricing_factor as totalll FROM market
where Currency='AUD' or Currency='INR' and Mkt_Price>100 group by Pricing_factor
and I got these results:
How can I collect(SUM) and reflect the resulting data ("INR"," AUD")? (Using SMSS)

SELECT Currency, SUM(Mkt_Price * Pricing_factor) AS Total
FROM market
WHERE Currency IN ('AUD', 'INR') AND Mkt_Price > 100
GROUP BY Currency;
Be careful with operator precedence:
Currency = 'AUD' OR Currency = 'INR' AND Mkt_Price > 100
Currency = 'AUD' OR (Currency = 'INR' AND Mkt_Price) > 100 -- same thing
This is what you really wanted:
(Currency = 'AUD' OR Currency = 'INR') AND Mkt_Price > 100
To combine the totals with a grand total you could try a union:
SELECT Currency, SUM(Mkt_Price * Pricing_factor) AS Total
FROM market
WHERE Currency IN ('AUD', 'INR') AND Mkt_Price > 100
GROUP BY Currency
UNION ALL
SELECT 'All', SUM(Mkt_Price * Pricing_factor) AS Total
FROM market
WHERE Currency IN ('AUD', 'INR') AND Mkt_Price > 100;
One you progress past understanding the basic operations you'll want to check into "grouping sets" and "rollup".

Related

How to Select and multiply certain columns based off criteria?

I am trying to write a code that is dynamic for European countries to capture the appropriate price based on the certain country. I am trying to pull data where the List Price is less than 4000, but wanted to add a statement that if the Currency is in SEK, then I want to multiply that list price by 10 and then if it's less than 4000 I want to include it. For other Currencies just take the list price as is for currency codes EUR, GBP, and CHF.
For example this is what I have and it's not working correctly:
SELECT
[Country_IBS]
,[Item_Number]
,[Price_List]
,List_Price
,[Currency]
FROM #temp4
WHERE List_Price < 4000
OR (SELECT List_Price * 10 WHERE Currency = 'SEK') < 4000
AND Currency = 'EUR'
OR Currency = 'GBP'
OR Currency = 'CHF'
I would do:
where
list_price * (case when currency = 'SEK' then 10 else 1 end) < 4000
and currency in ('EUR', 'GBP', 'CHF', 'SEK')
Or you can use the more verbose form:
where
(currency in ('EUR', 'GBP', 'CHF') and list_price < 4000)
or (currency = 'SEK' and price < 400)
AND has higher precedence than OR. You need to club you conditions in parentheses.
Your query should be like this:
--version 1: Using OR
SELECT
[Country_IBS]
,[Item_Number]
,[Price_List]
,List_Price
,[Currency]
FROM #temp4
WHERE (List_Price < 4000 AND Currency IN ('EUR','GBP','CHF'))
OR (List_Price * 10 < 4000 AND Currency = 'SEK')
--Version 2: Using UNION ALL
SELECT
[Country_IBS]
,[Item_Number]
,[Price_List]
,List_Price
,[Currency]
FROM #temp4
WHERE List_Price < 4000 AND Currency IN ('EUR','GBP','CHF')
UNION ALL
SELECT
[Country_IBS]
,[Item_Number]
,[Price_List]
,List_Price
,[Currency]
FROM #temp4
WHERE List_Price * 10 < 4000 AND Currency = 'SEK'
These queries returning same resultset might have different query plan as per indices created on your table. Use whichever is more efficient than another.
Explore Operator Precedence and UNION for more details.

sql multiplying a sum

I'm struggling with the below code. i'm trying to work out the total balance of a folio by using its total charges and total payments. i'm almost there, however with the below code the payments is incorrect, it seems to be multiplying the total sum of payments by the number of entries in charges. i'm guessing this is because I've connected the payments and charges, which I needed to do to filter out the checkin date which is only on pms sales.
can anyone help?
thanks
SELECT DISTINCT 'PMS AD' AS APP,
FOLIO_ID,
SUM(TOTAL_CHARGES) as TOTAL_CHARGES,
SUM(TOTAL_PAYMENTS) as TOTAL_PAYMENTS
FROM ((SELECT DISTINCT P1.FOLIO_ID AS FOLIO_ID, SUM(P1.CHARGE_CODE_AMOUNT) AS TOTAL_CHARGES, 0 AS TOTAL_PAYMENTS
FROM DEV.VR_PMS_SALES P1
WHERE P1.CHARGE_CODE_AMOUNT <> 0 AND
P1.ITEM_OPERATING_DAY IS NOT NULL
AND P1.ITEM_OPERATING_DAY <= '03-DEC-2014'
AND P1.CHECKIN_DATE <= '03-DEC-2014'
GROUP BY P1.FOLIO_ID
) UNION ALL
(SELECT DISTINCT P2.FOLIO_ID AS FOLIO_ID, 0 AS TOTAL_CHARGES, SUM(P2.AMOUNT) AS TOTAL_PAYMENTS
FROM DEV.VR_PMS_PAYMENTS P2,
DEV.VR_PMS_SALES P3
WHERE P2.FOLIO_ID = P3.FOLIO_ID
AND P2.AMOUNT <> 0
AND P2.PMS_OPERATING_DAY <= '03-DEC-2014'
AND P3.CHECKIN_DATE <= '03-DEC-2014'
GROUP BY P2.FOLIO_ID
)
) F
GROUP BY FOLIO_ID
EDIT:
Sorry I didn't provide examples. table data below
VR_PMS_PAYMENTS
VR_PMS_SALES
The issue I am having is that when running the sql it is multiplying the sum of p1.amount by the number of entries in VR_PMS_SALES. eg folio 4 is returning as 165 instead of 55. I need it to return the below...
desired outcome
I hope this is clearer.
thank you

Adding a currency conversion to a SQL query

I have a database with a list of user purchases.
I'm trying to extract a list of users whose last successful purchase had a value of £100 or greater, which I have done:
SELECT
t.purchase_id
t.user_id,
t.purchase_date,
t.amount,
t.currency,
FROM
transactions t
INNER JOIN
(SELECT user_id, MAX(purchase_date) AS first_transaction
FROM transactions
GROUP BY user_id) frst ON t.user_id = frst.user_id
AND t.created_date = frst.first_transaction
WHERE
amount >= 100
ORDER BY
user_id;
The problem is that some of my purchases are in USD and some are in CAD. I would like to ensure that the value of the latest purchase is over £100 GBP despite the purchase currency.
Luckily I have another table with exchange rates:
base_currency currency exchange_rate
-----------------------------------------------
GBP USD 1.220185624
GBP CAD 1.602048721
So technically I just need to convert the amount using the exchange rate. I've hit a roadblock on how I can incorporate that into my current query. I'm thinking I need to create an extra column for amount_in_gbp but am not sure how to incorporate the case logic into my query?
You can avoid any JOIN statement:
SELECT t.purchase_id
,t.user_id
,t.purchase_date
,t.amount
,t.currency
FROM transactions t
INNER JOIN (
SELECT user_id
,MAX(purchase_date) AS first_transaction
FROM transactions
GROUP BY user_id
) frst ON t.user_id = frst.user_id
AND t.created_date = frst.first_transaction
WHERE (
SELECT t.amount / e.exchange_rate
FROM exchange AS e
WHERE t.currency = e.currency
) >= 100
ORDER BY user_id;
So that your column will be converted in GBP currency.
You join to the table:
SELECT t.*,
(t.amount / exchange_rate) as amoung_gbp
FROM transactions t LEFT JOIN
exchange e
ON t.currency = e.currency AND e.base_currency = 'GBP'
If you want to put this in a where clause, you need to repeat the expression:
where (t.amount / exchange_rate) > 100

Grouping twice by different criteria, same column

I have data with the following columns:
OFFICER_ID, CLIENT_ID, SECURITY_CODE, POSITION_SIZE
and then per each row for instance:
officer1, client100, securityZYX, $100k,
officer2, client124, securityADF, $200k,
officer1, client130, securityARR, $150k,
officer4, client452, securityADF, $200k,
officer2, client124, securityARR, $500k,
officer7, client108, securityZYX, $223k,
and so on.
As you see, each client has a single officer assigned to either buy o sell securities, but each client can have bought different securities.
Apart from ranking officers by total amount in US$ of securities held by their clients (which I've done) I need to create ranges of total client accounts by adding total securities held by client ID, for example, total securities held sum < $1million, between $1million and $3million and > $3 million.
I've tried:
SELECT officer_ID, SUM(position_size) as AUM
FROM trades
GROUP BY client_ID
HAVING AUM > 1000000 AND AUM < 3000000;
and I get a list of all officers appearing several times, no totals.
I'd need a simple:
Officer_ID | range < 1m | range 1m-3m | range > 3m
officer1, [total amount of client accounts with securities adding up < 1m totals], [total amount of client accounts with securities adding up between 1m and 3m totals], etc.
Please, would you point me in the right direction?
UPDATE
I modified Tim's suggested code and obtained the desired output:
SELECT
OFFICER_ID,
SUM(CASE WHEN total < 1000000 THEN total END) AS "range < 1m",
SUM(CASE WHEN total >= 1000000 AND total < 3000000 THEN total END) AS "range 1m-3m",
SUM(CASE WHEN total >= 3000000 THEN total END) AS "range > 3m"
FROM
(
SELECT OFFICER_ID, CLIENT_ID, SUM(POSITION_SIZE) AS total
FROM trades
GROUP BY OFFICER_ID, CLIENT_ID
) t
GROUP BY
OFFICER_ID;
Too kind, Tim, thanks!
We can try aggregating twice, first by both officer and client, to get the client totals, and a second time by officer alone, to get the counts:
SELECT
OFFICER_ID,
COUNT(CASE WHEN total < 1000000 THEN 1 END) AS "range < 1m",
COUNT(CASE WHEN total >= 1000000 AND total < 3000000 THEN 1 END) AS "range 1m-3m",
COUNT(CASE WHEN total >= 3000000 THEN 1 END) AS "range > 3m"
FROM
(
SELECT OFFICER_ID, CLIENT_ID, SUM(POSITION_SIZE) AS total
FROM trades
GROUP BY OFFICER_ID, CLIENT_ID
) t
GROUP BY
OFFICER_ID;

Add a column into a select for calculation

I have 2 columns from a table and i want to add a third column to output the result of a calculation
select statement at the moment is:
select revenue, cost
from costdata
my 2 columns are revenue and cost
table name: costdata
my formula is: = ((revenue - cost)/ revenue)*100
I want the third column to be named 'result'
any idea on how to do this in a select statement?
SELECT revenue
, cost
, ((revenue - cost) / revenue) * 100 As result
FROM costdata
You mentioned in the comments that you get a divide by zero error. This wll occur when revenue equals zero.
What you want to happen in this scenario is up to you but this should get you started
SELECT revenue
, cost
, CASE WHEN revenue = 0 THEN
0
ELSE
((revenue - cost) / revenue) * 100
END As result
FROM costdata
Query:
SELECT revenue,
cost,
CASE WHEN revenue <> 0
THEN ((revenue - cost) / revenue) * 100
ELSE 0 END As result
FROM costdata
Try,
select revenue, cost,((revenue - cost)/ revenue)*100 AS result
from costdata
SELECT revenue, cost, ((revenue - cost)/ revenue)*100 AS result FROM costdata