sql quest with amount and exchange rate - sql

How to choose customers who have made a large amount of payments in December 2018 if we take into account the exchange rate
I have a table:
Trandate date - transaction date
Transum numeric (20,2) - amount of payment
CurrencyRate numeric (20,2) - currency exchange rate
ID_Client Trandate Transum CurrencyRate Currency
--------------------------------------------------------
1 2018.12.01 100 1 UAH
1 2018.12.02 150 2 USD
2 2018.12.01 200 1 UAH
3 2018.12.01 250 3 EUR
3 2018.12.02 300 1 UAH
3 2018.12.03 350 2 USD
7 2019.01.08 600 1 UAH
but I think that "max" is not at all what I need
SELECT ID_Client, MAX(Transum*CurrencyRate)
FROM `Payment.TotalPayments`
WHERE YEAR(Trandate) = 2018
AND MONTH(Trandate) = 12
I need something this
ID_Client Transum
3 1750
Where 1750 is a "UAH" and 350USD + 300UAH + 250EUR, exchange rate of USD is 2, exchange rate of EUR is 3.

If you're trying to get the sum of transaction amounts by client for the year 2018 and month of December, you could write it like this:
SELECT ID_Client, SUM(Transum*CurrencyRate) as payment_total_converted
FROM `Payment.TotalPayments`
WHERE YEAR(Trandate) = 2018
and MONTH(Trandate) = 12
group by ID_Client
If you want things grouped by each client, year, and month in a given date range, you'd write it like this:
SELECT ID_Client, YEAR(Trandate) as tran_year, MONTH(Trandate) as tran_month,
SUM(Transum*CurrencyRate) as payment_total_converted
FROM `Payment.TotalPayments`
WHERE Trandate between '2018-12-01' and '2019-01-01'
group by ID_Client, YEAR(Trandate), MONTH(Trandate)
I added a column name for your computed column so that the result set is still relational (columns need distinct names).
I'd recommend reading up on the SQL 'group by' clause (https://www.w3schools.com/sql/sql_groupby.asp) and aggregate (https://www.w3schools.com/sql/sql_count_avg_sum.asp, https://www.w3schools.com/sql/sql_min_max.asp) operators.

I think you want sum(). Then you can order by the result:
SELECT ID_Client, SUM(Transum*CurrencyRate) as total
FROM `Payment.TotalPayments`
WHERE Trandate >= '2018-12-01' AND Transdate < '2019-01-01'
GROUP BY ID_Client
ORDER BY total DESC;

Related

Sales for each completed month in current year and previous year

For each of the 12 months, I'm looking to create a field that sums the sales dollars at the account level for the most recent month and the 2nd most recent month based on the current date.
For example, given that today's date is 2022-10-28, 'MostRecentNovember' would sum up sales from November 2021. '2ndMostRecentNovember' would sum up sales from November 2020. Once the current date moves into November 2022, this query would adjust to pull MostRecentNovember sales from 2022 and 2ndMostRecentNovember sales from 2021.
Conversely, given that today's date is 2022-10-28 'MostRecentJune' would sum up sales from June 2022 and '2ndMostRecentJune' would sum up sales from June 2021.
In the end state, each account would have 24 fields: January - December for Most Recent and January - December for 2nd most recent
Below is my attempt at this code, this gets partially there, but it's not getting what I need. I've also tried with a CTE, but that didn't seem to do it either
SELECT NovemberMostRecent_Value =
sum(case when datepart(year,tran_date) = datepart(year, getdate())
AND DATEPART(month, tran_date) = 11 then value else 0 end)
NovemberSecondMostRecent_Value =
sum(case when datepart(year,tran_date) = datepart(year, getdate())-1
AND DATEPART(month, tran_date) = 11 then value else 0 end)
Here's a snippet of the source data table
account_no
tran_date
value
123
2021-11-22
500
123
2021-11-01
500
123
2020-11-20
1500
123
2022-06-03
5000
123
2021-06-04
2000
456
2020-11-03
525
456
2021-11-04
125
A table of desired Results
account_no
NovemberMostRecent
November2ndMostRecent
June MostRecent
June2ndMostRecent
123
1000
1500
5000
2000
456
125
525
0
0
We use dense_rank() by year desc (partitioned by month) and pivot.
select *
from
(
select account_no
,value
,concat(datename(month, tran_date), '_', dense_rank() over(partition by month(tran_date) order by year(tran_date) desc)) as month_rnk
from t
) t
pivot (sum(value) for month_rnk in(June_1, June_2, November_1, November_2)) p
account_no
June_1
June_2
November_1
November_2
123
5000
2000
1000
1500
456
null
null
125
525
Fiddle

POSTGRESQL - SUM of all orders with the same customer for a given month

I'm trying to produce a report with the total invoice amount for each customer in the month of December :
date
customer
invoice amount
01/12/2021
AB1
40
02/11/2021
AB2
60
12/12/2021
CE6
1000
31/12/2021
RF9
0.5
Could I get any pointers? I'm still fairly new to postgresql.
You should use GROUP BY for your purposes.
SELECT customer, SUM(invoice_amount) as total_invoice_amount
FROM your_table
WHERE EXTRACT(MONTH FROM date) = 12
GROUP BY customer

How to calculate average monthly number of some action in some perdion in Teradata SQL?

I have table in Teradata SQL like below:
ID trans_date
------------------------
123 | 2021-01-01
887 | 2021-01-15
123 | 2021-02-10
45 | 2021-03-11
789 | 2021-10-01
45 | 2021-09-02
And I need to calculate average monthly number of transactions made by customers in a period between 2021-01-01 and 2021-09-01, so client with "ID" = 789 will not be calculated because he made transaction later.
In the first month (01) were 2 transactions
In the second month was 1 transaction
In the third month was 1 transaction
In the nineth month was 1 transactions
So the result should be (2+1+1+1) / 4 = 1.25, isn't is ?
How can I calculate it in Teradata SQL? Of course I showed you sample of my data.
SELECT ID, AVG(txns) FROM
(SELECT ID, TRUNC(trans_date,'MON') as mth, COUNT(*) as txns
FROM mytable
-- WHERE condition matches the question but likely want to
-- use end date 2021-09-30 or use mth instead of trans_date
WHERE trans_date BETWEEN date'2021-01-01' and date'2021-09-01'
GROUP BY id, mth) mth_txn
GROUP BY id;
Your logic translated to SQL:
--(2+1+1+1) / 4
SELECT id, COUNT(*) / COUNT(DISTINCT TRUNC(trans_date,'MON')) AS avg_tx
FROM mytable
WHERE trans_date BETWEEN date'2021-01-01' and date'2021-09-01'
GROUP BY id;
You should compare to Fred's answer to see which is more efficent on your data.

SQL query: get total values for each month

I have a table that stores, number of fruits sold on each day. Stores number of items sold on particular date.
CREATE TABLE data
(
code VARCHAR2(50) NOT NULL,
amount NUMBER(5) NOT NULL,
DATE VARCHAR2(50) NOT NULL,
);
Sample data
code |amount| date
------+------+------------
aple | 1 | 01/01/2010
aple | 2 | 02/02/2010
orange| 3 | 03/03/2010
orange| 4 | 04/04/2010
I need to write a query, to list out, how many apple and orange sold for jan and february?
--total apple for jan
select sum(amount) from mg.drum d where date >='01/01/2010' and cdate < '01/02/2020' and code = 'aple';
--total apple for feb
select sum(amount) from mg.drum d where date >='01/02/2010' and cdate < '01/03/2020' and code = 'aple';
--total orange for jan
select sum(amount) from mg.drum d where date >='01/01/2010' and cdate < '01/02/2020' and code = 'orange';
--total orange for feb
select sum(amount) from mg.drum d where date >='01/02/2010' and cdate < '01/03/2020' and code = 'orange';
If I need to calculate for more months, more fruits, its tedious.is there a short query to write?
Can I combine at least for the months into 1 query? So 1 query to get total for each month for 1 fruit?
You can use conditional aggregation such as
SELECT TO_CHAR("date",'MM/YYYY') AS "Month/Year",
SUM( CASE WHEN code = 'apple' THEN amount END ) AS apple_sold,
SUM( CASE WHEN code = 'orange' THEN amount END ) AS orange_sold
FROM data
WHERE "date" BETWEEN date'2020-01-01' AND date'2020-02-29'
GROUP BY TO_CHAR("date",'MM/YYYY')
where date is a reserved keyword, cannot be a column name unless quoted.
Demo
select sum(amount), //date.month
from mg.drum
group by //date.month
//data.month Here you can give experssion which will return month number or name.
If you are dealing with months, then you should include the year as well. I would recommend:
SELECT TRUNC(date, 'MON') as yyyymm, code,
SUM(amount)
FROM t
GROUP BY TRUNC(date, 'MON'), code;
You can add a WHERE clause if you want only some dates or codes.
This will return a separate row for each row that has data. That is pretty close to the results from your four queries -- but this does not return 0 values.
select to_char(date_col,'MONTH') as month, code, sum(amount)
from mg.drum
group by to_char(date_col,'MONTH'), code

Datediff with dates in one column but only showing datediff compared to the next invoice

This is to understand how long it took the customer to pay a bill.
The datediff needs to be the next invoice to the payments
as Below example
ID Type1 Amount Date
--------------------------------------------------------------------
1 Invoice 38.16 2014-04-25
1 Payment -40.00 2014-03-23
1 Invoice 40.86 2014-02-22
1 Payment -40.00 2014-02-21
1 Invoice 42.21 2014-01-20
ID Type1 Amount Date DATEDIFF
---------------------------------------------------------
1 Invoice 38.16 2014-04-25
1 Payment -40.00 2014-03-23 29
1 Invoice 40.86 2014-02-22
1 Payment -40.00 2014-02-21 32
1 Invoice 42.21 2014-01-20
This can be done in many ways, one option is to use a correlated sub-query to get the date of the preceding row with item=invoice for all item=payment rows:
select
id, type1, amount, date,
datediff(day,
(select top 1 date
from table1
where date <= t.date
and type1= 'Invoice'
and t.type1='Payment'
order by date desc),
date) as diff
from table1 t;
This might not be the most efficient solution though.
Sample SQL Fiddle
Or you could use an outer apply with the same effect: http://www.sqlfiddle.com/#!6/b1e32/19