How to add serial number to a range query in SQL? - sql

I am selecting records within different ranges with a select statement like
select t.range as profit_range, count(*) as number_ of_occurences from (
select case
when t.range between 100000000 and 200000000 then '100 million - 200 million'
when t.range between 200000000 and 300000000 then '200 million - 300 million'
.
.
.
when t.range between 1000000000 and 2000000000 then '1000 million - 2000 million'
else 'Greater then 2000 milions' end as range
from tbl_profit) t
group by profit_range
This works but the order of the resulting rows is not correct
Profit_Range No_of_occurences
100 million - 200 million 4
1000 million - 2000 million 1
200 million - 300 million 4
How do I order the results to appear in the right order?

select t.range as [profit range], count(*) as [number of occurences]
from (
select case
when profit between 100000000 and 200000000 then '100 million - 200 million'
when profit between 200000000 and 300000000 then '200 million - 300 million'
.
.
.
when profit between 1000000000 and 2000000000 then '1000 million - 2000 million'
else 'Greater then 2000 milions' end as range
from tbl_profit) t
group by t.range
Order by SUBSTR(t.range,1,LOCATE(‘million’,t.range)-1)
You can extract starting number from range using SUBSTR() and LOCATE functions and order result according to extracted number

Related

How to create dynamic time intervals in SQL Snowflake?

I am writing a query that should recognize the dates when different budgets associated to one account were totally consumed. My start date is 1/12 so my task is to create a cumulative sum of the expenses that the account made for its first budget, then when the cumulative sum reach the budget, I should store the date when it happened, and the use that date as my new START DATE to compute the expenses of the same account but for the second budget, and so on. It seems for me difficult to create this dynamic interval was on the result of the previous budget. Do you have any idea of how I could I manage this problem?
What I Tried
WITH TRM_INTERVAL AS
(
SELECT
Country,
replace(Account_ID, '-', '') AS fixed_accountid,
TO_DATE(Date) AS CONVERTED_DATE,
TO_DATE(CAST(CONVERTED_DATE AS VARCHAR), 'YYYY-DD-MM') AS CONVERTED_DATE_FORMAT,
TRM2,
TRM1,
TOTAL_ARS_IN_ACCOUNT,
row_number()
over (partition by Account_ID, Country order by CONVERTED_DATE_FORMAT) AS ROW_NUMBER,
lag(TOTAL_ARS_IN_ACCOUNT)
over (partition by Account_ID, Country order by CONVERTED_DATE_FORMAT) AS PREVIOUS_ARS_BUCKET,
lead(CONVERTED_DATE_FORMAT)
over (partition by Account_ID, Country order by CONVERTED_DATE_FORMAT) AS NEXT_DATE
FROM CONECTOR
),
--DETAIL
DETAIL AS (
SELECT TI.COUNTRY, TI.fixed_accountid, TI.PREVIOUS_ARS_BUCKET, TI.TOTAL_ARS_IN_ACCOUNT, TI.ROW_NUMBER, GO.EVENT_DATE, SUM(CASE WHEN GO.CURRENCY_ORIGINAL = 'ARS' THEN GO.FINAL_CAC * 160 END) AS ARS_SPEND,
SUM(ARS_SPEND) OVER(PARTITION BY TI.fixed_accountid, TI.COUNTRY, TI.TOTAL_ARS_IN_ACCOUNT ORDER BY GO.EVENT_DATE ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS CUMULATIVE_ARS_SPEND
FROM TABLE1 AS GO
JOIN CONECTOR AS TI
ON GO.ACCOUNT_ID = TI.fixed_accountid AND GO.COUNTRY = TI.COUNTRY
WHERE GO.EVENT_DATE >= '2022-12-1'
GROUP BY 1,2,3,4,5,6
),
--ACUMULADO
LOGIC AS (
SELECT *,
CUMULATIVE_ARS_SPEND / TOTAL_ARS_IN_ACCOUNT AS CUMULATIVE_ARS_SPEND_PERCENTAGE,
--COMO VALIDAR CON EL TI TOTAL ARS CORRESPONDIENTE
CASE WHEN CUMULATIVE_ARS_SPEND_PERCENTAGE >=0.686 AND EVENT_DATE <> CURRENT_DATE() THEN 'FLAG' END AS FLAGS
FROM DETAIL
)
I have 3 subqueries. To sum up, I create the cumulative sum of the expenses related to each account but I could not create the dynamic intervals. The dates start from 12/1/2022.
What actually resulted
You see 3 budgets as example. All of them are associated with a single account. I start with the budget 500,000, you see that I made the cumulative sum until it reach 100%. but then for the second budget 30,000,000 the dates and the expenses are repeated. The same dates were applied 1/12, 1/13, 1/14 and 1/15. The idea is that if the first budget was totally consumed on 1/15 as you can see, the query should compute the expenses for the second budget since one day later 1/16 until that second budget is as well totally consumed and so on.
FECHA BUDGET SPEND_DAILY CUMULATIVE % ACUMM
01/12/2022 500000 100000 100000 20.00%
01/13/2022 500000 150000 250000 50.00%
01/14/2022 500000 200000 450000 90.00%
01/15/2022 500000 50000 500000 100.00%
01/12/2022 30000000 100000 100000 0.33%
01/13/2022 30000000 150000 250000 0.83%
01/14/2022 30000000 200000 450000 1.50%
01/15/2022 30000000 50000 500000 1.67%
01/12/2022 4000000 100000 100000 2.50%
01/13/2022 4000000 150000 250000 6.25%
01/14/2022 4000000 200000 450000 11.25%
01/15/2022 4000000 50000 500000 12.50%
What I expected to happen
The desire output should be these table, where the first budget is totally consumed one day, and on the next day, the expenses compute is updated and now the cumulative sum is applied to the second budget.
FECHA BUDGET GASTO DIARIO GASTO ACUMM % ACUMM
01/12/2022 500000 100000 100000 20.00%
01/13/2022 500000 150000 250000 50.00%
01/14/2022 500000 200000 450000 90.00%
01/15/2022 500000 50000 500000 100.00%
01/16/2022 30000000 100000 100000 0.33%
01/17/2022 30000000 200000 300000 1.00%
01/18/2022 30000000 500000 800000 2.67%
01/19/2022 30000000 300000 1100000 3.67%
01/20/2022 30000000 150000 1250000 4.17%
01/21/2022 30000000 20000000 21250000 70.83%
01/22/2022 30000000 10000000 31250000 104.17%

Slab based calculation in SQL

I want to calculate the slab based logic.
This is my table where the min_bucket and max_bucket range is mention and also the rate of it.
slabs min_bucket max_bucket rate_per_month
----------------------------------------------
Slab 1 0 300000 20
Slab 2 300000 500000 17
Slab 3 500000 1000000 14
Slab 4 1000000 13
We need to calculate as
If there are 450k subs, the payout will be 300k20 + 150k17
If the Total Count is 1000001, then its output should be as
min_bucket max_bucket rate_per_month Count rate_per_month revenue
-----------------------------------------------------------------------
0 300000 20 300000 20 6000000
300000 500000 17 500000 17 8500000
500000 1000000 14 200001 14 2800014
Where count is calculated as 300000+500000+200001 = 1000001, and revenue is calculated as rate_per_month * Count as per the slab.
Can anyone help me write the SQL query for this, which will handle all the cases?
You can build running totals of the slabs table and work with them:
with given as (select 1000001 as value)
, slabs as
(
select
slab,
min_bucket,
max_bucket,
rate_per_month,
sum(min_bucket) over (order by min_bucket) as sum_min_bucket,
sum(coalesce(max_bucket, 2147483647)) over (order by min_bucket) as sum_max_bucket
from mytable
)
select
slabs.slab,
slabs.min_bucket,
slabs.max_bucket,
slabs.rate_per_month,
case when slabs.sum_max_bucket <= given.value
then slabs.max_bucket
else given.value - sum_min_bucket
end as used,
case when slabs.sum_max_bucket <= given.value
then slabs.max_bucket
else given.value - sum_min_bucket
end * slabs.rate_per_month as revenue
from given
join slabs on slabs.sum_min_bucket < given.value
order by slabs.min_bucket;
I don't know your DBMS, but this is standard SQL and likely to work for you (either right away or with a little tweak).
Demo: https://dbfiddle.uk/?rdbms=postgres_13&fiddle=9c4f5f837b6167c7e4f2f7e571f4b26f

Use columns as where and has subtraction in it

My problem is I just wanna show all the unpaid rows:
I have this data:
id name commission paid
1 James 15000 2000
2 Curry 15000 15000
3 Durant 15000 0
4 Wade 15000 5000
5 Harden 15000 15000
I wanted to get only the rows that are not gonna be equal to 0, I wanted to use where clause for commission - paid if it is greater than 0
Output that I would expect is:
id name commission paid
1 James 15000 2000
3 Durant 15000 0
4 Wade 15000 5000
SELECT * FROM table_name WHERE (commission - paid) > 0
Or
SELECT * FROM table_name WHERE commission!=paid
This will work too because either subtraction will be greater than zero or 0 (assuming paid amount is always less than commission)
You can use the following solution using a simple calculation on WHERE:
SELECT * FROM table_name WHERE commission - paid > 0
You can also use the following:
SELECT * FROM table_name WHERE commission > paid
Note: In this case someone can overpay the commission. Using != or <> the overpay would be found as not paid.
demo: https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=a391576f2df2c5d7c8616485b2c70099
To get all paid rows you can use the following:
SELECT * FROM table_name WHERE commission - paid <= 0
or ...
SELECT * FROM table_name WHERE commission <= paid
you can use the following query given below using WHERE clause
SELECT * FROM commision_table_name WHERE (commission - paid) > 0;

MS-Access : How to sum multiple values from different tables according to dates

I have two similar tables as follows
Table 1
Date Amount Tax
4/1/2016 1000 100
4/1/2016 2000 200
5/3/2016 1500 150
5/6/2016 1000 100
5/6/2016 3000 300
7/9/2016 2500 250
Table 2
Date Amount Tax
4/1/2016 1000 100
4/2/2016 3000 300
5/3/2016 1500 150
5/9/2016 4000 400
8/11/2016 3000 300
10/9/2016 2000 200
dates can be similar or different in both tables.
I want two queries.
First, a query which gives me sum of amount and tax from each date from both tables between required dates. Eg: Table 1 have 2 entries and table 2 have 1 entry for 4/1/2016. so the result should be as below (summing up all three entries)
Date Amount Tax
4/1/2016 4000 400
4/2/2016 3000 300
5/3/2016 3000 300
5/6/2016 4000 400
5/9/2016 4000 400
7/9/2016 2500 250
8/11/2016 3000 300
10/9/2016 2000 200
Second,a query which gives of sum of amount and tax for each month from both tables between required dates. Eg output as below
Date Amount Tax
4/2016 4000 400
5/2016 11000 1100
7/2016 2500 250
8/2016 3000 300
10/2016 2000 200
Query that have I have written till now( not working )
SELECT date, sum(Amount),sum(Tax)
From Table1
WHERE Date BETWEEN #04/01/2016# AND #12/31/2016#
UNION ALL
SELECT date, sum(Amount),sum(Tax)
From Table2
WHERE Date BETWEEN #04/01/2016# AND #12/31/2016#
GROUP BY Date
For first query, consider a union query derived table with outer query aggregation:
SELECT q1.[Date], SUM(q1.Amount) AS DayTotalAmt, SUM(q1.Tax) AS DayTotalTax
FROM
(SELECT [Date], Amount, Tax
FROM Table1
UNION ALL
SELECT [Date], Amount, Tax
FROM Table2
) AS q1
GROUP BY q1.[Date]
For second query, consider using first query as a source with another outer query layer that runs a WHERE filter with month/year aggregation:
SELECT Format(q2.Date, "M/YYYY"), SUM(q2.DayTotalAmt) AS MonthTotalAmt,
SUM(q2.DayTotalTax) AS MonthTotalTax
FROM
(SELECT q1.[Date], SUM(q1.Amount) AS DayTotalAmt, SUM(q1.Tax) AS DayTotalTax
FROM
(SELECT [Date], Amount, Tax
FROM Table1
UNION ALL
SELECT [Date], Amount, Tax
FROM Table2) AS q1
GROUP BY q1.[Date]
) AS q2
WHERE q2.Date BETWEEN CDate("4/1/2016") AND CDate("12/31/2016")
GROUP BY Format(q2.Date, "M/YYYY")
Or if you save first query:
SELECT Format(q.Date, "M/YYYY"), SUM(q.DayTotalAmt) AS MonthTotalAmt,
SUM(q.DayTotalTax) AS MonthTotalTax
FROM Query1 q
WHERE q.Date BETWEEN CDate("4/1/2016") AND CDate("12/31/2016")
GROUP BY Format(q.Date, "M/YYYY")

sum without duplicates RDLC

I have a report in RDLC. I try to sum up without duplicates. So how to sum ignoring duplicates??
№ sale Date_Sales Amount Date_payment Amount
01-01 01/07/2013 1000 15/07/2013 500
01-01 01/07/2013 1000 18/07/2013 500
Total 2000 1000
and should be:
№ sale Date_Sales Amount Date_payment Amount
01-01 01/07/2013 1000 15/07/2013 500
01-01 01/07/2013 1000 18/07/2013 500
Total 1000 1000
I hide duplicates in the second line but I can't avoid the sum of this duplicate fields. I need to see the sum of sales and the sum of payments in the same report.
In SQL it would be
SELECT SUM(columnname) AS iSum FROM(
SELECT DISTINCT columnname FROM tablename) AS foo