Round timestamp to 30 minutes interval to group by - sql

Problem
select currency,
MAX (CASE WHEN type = 'Bank A' THEN rate ELSE null END) as bank_a_rate,
MAX (CASE WHEN type = 'Bank B' THEN rate ELSE null END) as bank_b_rate
from rates
group by currency, created
I want to group my data by currency, timestamp and show all type value like table of comparison with interval of 30 minutes, for now my created time is 1 minute or less different so if i group with created time it will still showing 4 rows cause of different timestamp, is there a way to round the timestamp ?
Data Source
Type
Currency
Rate
Created
Bank A
USD
3.4
2020-01-01 12:29:15
Bank B
USD
3.34
2020-01-01 12:30:11
Bank A
EUR
4.92
2020-01-01 12:31:01
Bank B
EUR
5.03
2020-01-01 12:31:14
Expected Result
Timestamp
Currency
Bank A Rate
Bank B Rate
2020-01-01 12:30:00
USD
3.4
3.34
2020-01-01 12:30:00
EUR
4.92
5.03

Truncate/round created to 30 minutes (the ts expression) and group by it. Your query with this amendment:
select date_trunc('hour', created) +
interval '1 minute' * (extract(minute from created)::integer/30)*30 AS ts,
currency,
MAX (CASE WHEN "type" = 'Bank A' THEN rate ELSE null END) as bank_a_rate,
MAX (CASE WHEN "type" = 'Bank B' THEN rate ELSE null END) as bank_b_rate
from rates
group by currency, ts;
SQL Fiddle
'Inherit' previous rate
select ts, currency,
coalesce(bank_a_rate, lag(bank_a_rate) over w) bank_a_rate,
coalesce(bank_b_rate, lag(bank_b_rate) over w) bank_b_rate
from
(
select date_trunc('hour', created) +
interval '1 minute' * (extract(minute from created)::integer/30)*30 ts,
currency,
MAX (CASE WHEN "type" = 'Bank A' THEN rate ELSE null END) as bank_a_rate,
MAX (CASE WHEN "type" = 'Bank B' THEN rate ELSE null END) as bank_b_rate
from rates
group by currency, ts
) t
window w as (partition by currency order by ts);
SQL Fiddle

One method uses epoch for this purpose and then converting the seconds to 30 minutes intervals using arithmetic:
select '1970-01-01'::timestamp + floor(extract(epoch from created) / (24 * 60 * 2)) * (24 * 60 * 2) * interval '1 second' as timestamp,
currency,
MAX (CASE WHEN type = 'Bank A' THEN rate ELSE null END) as bank_a_rate,
MAX (CASE WHEN type = 'Bank B' THEN rate ELSE null END) as bank_b_rate
from rates
group by timestamp, currency;

Related

unpivot columns, sum of value into one row group by other column based on start_month column that is bound to change

I have these data,
item
start_month
month_m_qty
month_m1_qty
month_m2_qty
month_m3_qty
month_m4_qty
month_m5_qty
A
202207
1000
200
4000
480
4000
0
B
202207
10
2400
0
234
304
0
C
202207
300
2000
480
1000
0
0
D
202207
900
700
200
0
4000
0
I would like to pivot this table to have one column time_period et one column with qty and this group by Item.
The column month goes to month_m17_qty but, i would like to retrieve only month of the year of the start_month like this
result expected:
item
time_period
qty
A
202207
1000
A
202208
200
A
202209
4000
A
202210
480
A
202211
4000
A
202212
0
B
202207
10
B
202208
2400
B
202209
0
B
202210
234
B
202211
304
B
202212
0
At the moment i used this script:
DECLARE get_col_names STRING;
SET get_col_names = (
SELECT CONCAT('(', STRING_AGG( column_name, ','), ')'),
From(
SELECT column_name,
FROM path_table.INFORMATION_SCHEMA.COLUMNS
where table_name ="table" and column_name LIKE ("%quantity")));
EXECUTE IMMEDIATE format("""
CREATE OR REPLACE TABLE tableA AS (
select item, start_month, time_period, qty
from table
unpivot
(
qty for time_period IN %s
) )
""", get_col_names);
WITH TEMP AS (
SELECT
item, PARSE_DATE('%Y%m', CAST (start_month AS STRING)) as start_month, time_period, qty
FROM tableA),
TEMP2 AS (
SELECT item,
CASE
WHEN time_period = 'month_m_quantity' THEN start_month
WHEN time_period = 'month_m1_quantity' THEN DATE_ADD(start_month, INTERVAL 1 MONTH)
WHEN time_period = 'month_m2_quantity' THEN DATE_ADD(start_month, INTERVAL 2 MONTH)
WHEN time_period = 'month_m3_quantity' THEN DATE_ADD(start_month, INTERVAL 3 MONTH)
WHEN time_period = 'month_m4_quantity' THEN DATE_ADD(start_month, INTERVAL 4 MONTH)
WHEN time_period = 'month_m5_quantity' THEN DATE_ADD(start_month, INTERVAL 5 MONTH)
WHEN time_period = 'month_m6_quantity' THEN DATE_ADD(start_month, INTERVAL 6 MONTH)
WHEN time_period = 'month_m7_quantity' THEN DATE_ADD(start_month, INTERVAL 7 MONTH)
WHEN time_period = 'month_m8_quantity' THEN DATE_ADD(start_month, INTERVAL 8 MONTH)
WHEN time_period = 'month_m9_quantity' THEN DATE_ADD(start_month, INTERVAL 9 MONTH)
WHEN time_period = 'month_m10_quantity' THEN DATE_ADD(start_month, INTERVAL 10 MONTH)
WHEN time_period = 'month_m11_quantity' THEN DATE_ADD(start_month, INTERVAL 11 MONTH)
WHEN time_period = 'month_m12_quantity' THEN DATE_ADD(start_month, INTERVAL 12 MONTH)
END AS time_period,
start_month,
qty
FROM TEMP)
SELECT
*
FROM TEMP2
WHERE EXTRACT(YEAR FROM time_period) = EXTRACT(YEAR FROM start_month)
Is there a better way to optimize the renaming in date format into new column like this month_m_qty -> 202207 , month_m1_qty -> 202208, month_m2_qty -> 202209 etc
How can i make this ?
Many thanks in advance for your help
Consider below approach
select item, format_date('%Y%m', time_period) time_period, value
from (
select *,
date_add(parse_date('%Y%m', '' || start_month),
interval ifnull(cast(regexp_extract(month, r'\d+') as int64), 0) month
) time_period
from (
select * from your_table
unpivot (value for month in (
month_m_qty, month_m1_qty, month_m2_qty, month_m3_qty, month_m4_qty, month_m5_qty
# ,month_m6_qty, month_m7_qty, month_m8_qty, month_m9_qty, month_m10_qty, month_m11_qty
# ,month_m12_qty, month_m13_qty, month_m14_qty, month_m15_qty, month_m16_qty, month_m17_qty
))
)
)
where extract(year from parse_date('%Y%m', '' || start_month)) = extract(year from time_period)
if applied to sample data in your question - output is

Percentage Difference Using CASE WHEN clause

The table I am working with is called 'transactions'. The columns are id (customer id), amount (amount spent by customer), timestamp (time of purchase).
I am trying to query:
yesterdays revenue: sum of amount.
percent difference from 8 day's ago revenue to yesterday's revenue.
MTD.
percent difference from last months MTD to this months MTD.
SAMPLE DATA
id
amount
timestamp
1
50
2021-12-01
2
60
2021-12-02
3
70
2021-11-05
4
80
2022-01-26
5
90
2022-01-25
6
20
2022-01-26
7
80
2022-01-19
EXPECTED OUTPUT
yesterday_revenue
pct_change_week_ago
mtd
pct_change_month_prior
100
0.25
270
0.50
This is my code. The percent change columns are both incorrect. Please help.
select
-- yesterday
sum(case when timestamp::date = current_date - 1 then amount else null end) yesterday_revenue,
-- yesterday v. last week
(sum(case when timestamp::date > current_date - 1 then amount else null end) - sum(case when timestamp::date = current_date - 8 then amount else null end))
/ sum(case when timestamp::date = current_date - 8 then amount else null end) pct_change_week_ago,
-- mtd
sum(case when date_trunc('month',timestamp) = date_trunc('month',CURRENT_DATE -1) then amount else null end) mtd,
-- mtd v. month prior
(sum(case when date_trunc('month',timestamp) = date_trunc('month',CURRENT_DATE -1) then amount else null end) - sum(case when date_trunc('month',timestamp) = date_trunc('month',CURRENT_DATE -1) - interval '1 month'
and date_part('day',timestamp ) <= date_part('day', CURRENT_DATE -1) then amount else null end))
/ sum(case when date_trunc('month',timestamp) = date_trunc('month',CURRENT_DATE -1) - interval '1 month'
and date_part('day',timestamp ) <= date_part('day', CURRENT_DATE -1) then amount else null end) pct_change_month_prior
from transactions
Some things to consider:
"yesterday vs last week" currently uses timestamp::date > current_date - 1 at the start. This will include transactions from today only, not yesterday (it says "greater than yesterday"). I think it should be timestamp::date = current_date - 1
I could be wrong here, but I think sum(case when date_trunc('month',timestamp) = date_trunc('month',CURRENT_DATE -1) will capture transactions on the current date as well if the current date is in the same month as yesterday. You may not want that.
As far as I can tell, 'pct_change_month_prior' should be 1.45, not 0.5. You have 110 in December and 270 in January. 270 - 110 = 160 and 160 / 110 = 1.45. Your existing query already returns that result. FWIW, you can also use new/old-1 to get the same result in a slightly simpler way.
OK, so really, it's about your maths in the SELECT part of your statement.
Amount changed is: new - old
As a multiplicative amount, it is (new - old) / old or new / old - 1
As a percentage, you need to multiply by 100... 100 * (new / old - 1) but I understand you aren't worried about this.
Further to this, let's make sure your new and old are correct.
Yesterday's sum:
sum(case when timestamp::date = CURRENT_DATE - 1 then amount else null end)
8 days ago sum:
sum(case when timestamp::date = CURRENT_DATE - 8 then amount else null end)
1 month to yesterday sum:
sum(case when timestamp::date > CURRENT_DATE - 1 - INTERVAL '1 month' AND timestamp::date <= CURRENT_DATE - 1 then amount else null end)
1 month to 1 month and 1 day ago sum:
sum(case when timestamp::date > CURRENT_DATE - 1 - INTERVAL '2 month' AND timestamp::date <= CURRENT_DATE - 1 - INTERVAL '1 month' then amount else null end)
Start of month to yesterday sum:
sum(case when timestamp::date > DATE_TRUNC('month', CURRENT_DATE - 1) AND timestamp::date <= CURRENT_DATE - 1 then amount else null end)
Start of yesterday's last month to a month ago yesterday sum:
sum(case when timestamp::date > DATE_TRUNC('month', CURRENT_DATE - 1 - INTERVAL '1 month') AND timestamp::date <= CURRENT_DATE - 1 - INTERVAL '1 month' then amount else null end)
It's important you don't change = to > or cropping to just the date part else you will include more than you really want.
Effectively, by cropping to the month part, it would almost always sum all transactions for two months.

SQL why does dateA - dateB <= '3 years' give a different result than dateA <= dateB + '3 years'

I was doing a MODE.com SQL practice question about date format.
The practice question is: Write a query that counts the number of companies acquired within 3 years, 5 years, and 10 years of being founded (in 3 separate columns). Include a column for total companies acquired as well. Group by category and limit to only rows with a founding date.
It uses two tables:
tutorial.crunchbase_companies_clean_date table, which includes information about all the companies, like company name, founded year, etc.
tutorial.crunchbase_acquisitions_clean_datetable, which includes the information about all the acquired companies, like acquired company name, acquired date, etc.
My code is:
SELECT companies.category_code,
COUNT(CASE WHEN acq.acquired_at_cleaned - companies.founded_at_clean:: timestamp <= '3 years' THEN 1 ELSE NULL END) AS less_than_3_years,
COUNT(CASE WHEN acq.acquired_at_cleaned - companies.founded_at_clean:: timestamp <= '5 years' THEN 1 ELSE NULL END) AS between_3_to_5_years,
COUNT(CASE WHEN acq.acquired_at_cleaned - companies.founded_at_clean:: timestamp <= '10 years' THEN 1 ELSE NULL END) AS within_10_years,
COUNT(1) AS total
FROM tutorial.crunchbase_companies_clean_date companies
JOIN tutorial.crunchbase_acquisitions_clean_date acq
ON companies.permalink = acq.company_permalink
WHERE companies.founded_at_clean IS NOT NULL
GROUP BY 1
ORDER BY total DESC
The result is:
My result
The answer query is:
SELECT companies.category_code,
COUNT(CASE WHEN acquisitions.acquired_at_cleaned <= companies.founded_at_clean::timestamp + INTERVAL '3 years'
THEN 1 ELSE NULL END) AS acquired_3_yrs,
COUNT(CASE WHEN acquisitions.acquired_at_cleaned <= companies.founded_at_clean::timestamp + INTERVAL '5 years'
THEN 1 ELSE NULL END) AS acquired_5_yrs,
COUNT(CASE WHEN acquisitions.acquired_at_cleaned <= companies.founded_at_clean::timestamp + INTERVAL '10 years'
THEN 1 ELSE NULL END) AS acquired_10_yrs,
COUNT(1) AS total
FROM tutorial.crunchbase_companies_clean_date companies
JOIN tutorial.crunchbase_acquisitions_clean_date acquisitions
ON acquisitions.company_permalink = companies.permalink
WHERE founded_at_clean IS NOT NULL
GROUP BY 1
ORDER BY 5 DESC
The result is:
The answer result
You can see in the screenshots that the results are very similar, but some numbers are different.
The only difference I can see between my query and the answer is in the COUNT statements, but I don't really see the difference, for example, between: acq.acquired_at_cleaned - companies.founded_at_clean:: timestamp <= '3 years' and acquisitions.acquired_at_cleaned <= companies.founded_at_clean::timestamp + INTERVAL '3 years'
I tried adding INTERVAL in my SELECT statement:
SELECT companies.category_code,
COUNT(CASE WHEN acq.acquired_at_cleaned - companies.founded_at_clean:: timestamp <= INTERVAL '3 years' THEN 1 ELSE NULL END) AS less_than_3_years,
COUNT(CASE WHEN acq.acquired_at_cleaned - companies.founded_at_clean:: timestamp <= INTERVAL '5 years' THEN 1 ELSE NULL END) AS between_3_to_5_years,
COUNT(CASE WHEN acq.acquired_at_cleaned - companies.founded_at_clean:: timestamp <= INTERVAL '10 years' THEN 1 ELSE NULL END) AS within_10_years,
COUNT(1) AS total
and remove the INTERVAL from the answer query:
SELECT companies.category_code,
COUNT(CASE WHEN acquisitions.acquired_at_cleaned <= companies.founded_at_clean::timestamp + '3 years'
THEN 1 ELSE NULL END) AS acquired_3_yrs,
COUNT(CASE WHEN acquisitions.acquired_at_cleaned <= companies.founded_at_clean::timestamp + '5 years'
THEN 1 ELSE NULL END) AS acquired_5_yrs,
COUNT(CASE WHEN acquisitions.acquired_at_cleaned <= companies.founded_at_clean::timestamp + '10 years'
THEN 1 ELSE NULL END) AS acquired_10_yrs,
COUNT(1) AS total
But the results are the same.
I tried to know the result of just the difference between the acquired_date and founded_date, to see if the value can be compared with INTERVAL. The result is in days, which looks promising to me.
The result
I try to give all the information for your consideration. Hope somebody could help. Thank you in advance!
My suggestion is to add/subtract the INTERVAL to/from one date/time and then compare with the other date/time. Don't subtract the date/times and then compare to a string literal. Your database seems to understand '3 YEARS' as 3 * 365 days, regardless of the actual number of days between someDateTime and someDateTime +/- '3 YEARS'. The actual number of days from year to year could be 365 or 366, depending on whether a leap year is crossed.
Here's a simple example of comparing with a specific interval, which also requires we know whether and how many leap years were crossed.
Fiddle
The test case:
WITH dates AS (
SELECT '2021-01-01'::date AS xdate
)
SELECT xdate - (xdate - INTERVAL '1' YEAR) AS diff
, xdate - (xdate - INTERVAL '1' YEAR) = '1 YEAR' AS b1
, xdate - (xdate - INTERVAL '1' YEAR) = '365 DAYS' AS b2
, xdate - (xdate - INTERVAL '1' YEAR) = '366 DAYS' AS b3
FROM dates
;
-- AND --
WITH dates AS (
SELECT '2021-01-01'::date AS xdate
)
SELECT xdate - (xdate - INTERVAL '1' YEAR) AS diff
, xdate - (xdate - INTERVAL '1' YEAR) = INTERVAL '1' YEAR AS b1
, xdate - (xdate - INTERVAL '1' YEAR) = INTERVAL '365 DAYS' AS b2
, xdate - (xdate - INTERVAL '1' YEAR) = INTERVAL '366 DAYS' AS b3
FROM dates
;
Result:
diff
b1
b2
b3
366 days
f
f
t
Fiddle
WITH dates AS (
SELECT '2021-01-01'::date AS xdate
)
, diff AS (
SELECT xdate - (xdate - INTERVAL '1' YEAR) AS diff
FROM dates
)
SELECT diff
, CASE WHEN diff = (366*24*60*60 * INTERVAL '1' SECOND)
THEN 1
END AS compare1
, 366*24*60*60 AS seconds
, CASE WHEN diff = (366*24*60*60 * INTERVAL '1' SECOND)
THEN 1
END AS compare2
, CASE WHEN diff = '31622400 SECONDS'
THEN 1
END AS compare3
FROM diff
;
The result:
diff
compare1
seconds
compare2
compare3
366 days
1
31622400
1
1
Original response:
The fiddle for PostgreSQL
The behavior shown here (below) is similar to the posted behavior.
The problem is the value generated isn't necessarily what you think.
Here's a test case in postgresql which might be representative of your issue.
Maybe this is related to leap year, where the number of days in a year isn't constant.
So it's probably safer to compare the dates rather than assume some number of days, which is probably the assumption <= '3 years' makes.
The test SQL:
WITH test (acquired_at_cleaned, founded_at_clean, n) AS (
SELECT current_date, current_date - INTERVAL '4' YEAR, 4 UNION
SELECT current_date, current_date - INTERVAL '3' YEAR, 3 UNION
SELECT current_date, current_date - INTERVAL '2' YEAR, 2 UNION
SELECT current_date, current_date - INTERVAL '1' YEAR, 1
)
, cases AS (
SELECT test.*
, CASE WHEN acquired_at_cleaned <= founded_at_clean::timestamp + INTERVAL '3' year
THEN 1 ELSE NULL
END AS acquired_3_yrs_case1
, CASE WHEN acquired_at_cleaned - founded_at_clean::timestamp <= '3 year'
THEN 1 ELSE NULL
END AS acquired_3_yrs_case2
, acquired_at_cleaned - founded_at_clean::timestamp AS x1
, acquired_at_cleaned - (n * INTERVAL '1' YEAR) AS x2
FROM test
)
SELECT acquired_at_cleaned AS acquired
, founded_at_clean AS founded
, n
, acquired_3_yrs_case1 AS case1
, acquired_3_yrs_case2 AS case2
, x1, x2
FROM cases
ORDER BY founded_at_clean
;
The result:
acquired
founded
n
case1
case2
x1
x2
2021-12-25
2017-12-25 00:00:00
4
null
null
1461 days
2017-12-26 00:00:00
2021-12-25
2018-12-25 00:00:00
3
1
null
1096 days
2018-12-26 00:00:00
2021-12-25
2019-12-25 00:00:00
2
1
1
731 days
2019-12-26 00:00:00
2021-12-25
2020-12-25 00:00:00
1
1
1
365 days
2020-12-26 00:00:00
Interesting result.

Split monthly fix value to days and countries in Redshift

DB-Fiddle
CREATE TABLE sales (
id SERIAL PRIMARY KEY,
country VARCHAR(255),
sales_date DATE,
sales_volume DECIMAL,
fix_costs DECIMAL
);
INSERT INTO sales
(country, sales_date, sales_volume, fix_costs
)
VALUES
('DE', '2020-01-03', '500', '2000'),
('NL', '2020-01-03', '320', '2000'),
('FR', '2020-01-03', '350', '2000'),
('None', '2020-01-31', '0', '2000'),
('DE', '2020-02-15', '0', '5000'),
('NL', '2020-02-15', '0', '5000'),
('FR', '2020-02-15', '0', '5000'),
('None', '2020-02-29', '0', '5000'),
('DE', '2020-03-27', '180', '4000'),
('NL', '2020-03-27', '670', '4000'),
('FR', '2020-03-27', '970', '4000'),
('None', '2020-03-31', '0', '4000');
Expected Result:
sales_date | country | sales_volume | used_fix_costs
-------------|--------------|------------------|------------------------------------------
2020-01-03 | DE | 500 | 37.95 (= 2000/31 = 64.5 x 0.59)
2020-01-03 | FR | 350 | 26.57 (= 2000/31 = 64.5 x 0.41)
2020-01-03 | NL | 320 | 0.00
-------------|--------------|------------------|------------------------------------------
2020-02-15 | DE | 0 | 86.21 (= 5000/28 = 172.4 x 0.50)
2020-02-15 | FR | 0 | 86.21 (= 5000/28 = 172.4 x 0.50)
2020-02-15 | NL | 0 | 0.00
-------------|--------------|------------------|------------------------------------------
2020-03-27 | DE | 180 | 20.20 (= 4000/31 = 129.0 x 0.16)
2020-03-27 | FR | 970 | 108.84 (= 4000/31 = 129.0 x 0.84)
2020-03-27 | NL | 670 | 0.00
-------------|--------------|------------------|-------------------------------------------
The column used_fix_costs in the expected result is calculated as the following:
Step 1) Exclude country NL from the next steps but it should still appear with value 0 in the results.
Step 2) Get the daily rate of the fix_costs per month.(2000/31 = 64.5; 5000/29 = 172.4; 4000/31 = 129.0)
Step 3) Split the daily value to the countries DE and FR based on their share in the sales_volume. (500/850 = 0.59; 350/850 = 0.41; 180/1150 = 0.16; 970/1150 = 0.84)
Step 4) In case the sales_volume is 0 the daily rate gets split 50/50 to DE and FR as you can see for 2020-02-15.
I am currently using this query to get the expected results:
SELECT
s.sales_date,
s.country,
s.sales_volume,
s.fix_costs,
(CASE WHEN country = 'NL' THEN 0
/* Exclude NL from fixed_costs calculation */
WHEN SUM(CASE WHEN country <> 'NL' THEN sales_volume ELSE 0 END) OVER (PARTITION BY sales_date) > 0
THEN ((s.fix_costs/ extract(day FROM (date_trunc('month', sales_date + INTERVAL '1 month') - INTERVAL '1 day'))) *
sales_volume /
NULLIF(SUM(s.sales_volume) FILTER (WHERE s.country != 'NL') OVER (PARTITION BY s.sales_date), 0)
)
/* Divide fixed_cots equaly among countries in case of no sale*/
ELSE (s.fix_costs / extract(day FROM (date_trunc('month', sales_date + INTERVAL '1 month') - INTERVAL '1 day')))
/ SUM(CASE WHEN country <> 'NL' THEN 1 ELSE 0 END) OVER (PARTITION by sales_date)
END) AS imputed_fix_costs
FROM sales s
WHERE country NOT IN ('None')
GROUP BY 1,2,3,4
ORDER BY 1;
This query works in the DB-Fiddle.
However, when I run it on Amazon Redshift I get this error message for the line
FILTER (WHERE pl.sales_Channel NOT IN ('Marketplace','B2B')).
Do you have any idea how I can replace/adjust this part of the query to also make it work in Amazon Redshift?
If I understand correctly, you want to define apportioned fixed costs per day for all countries other than NL:
select s.*,
(case when country = 'NL' then 0
when sum(sales_volume) over (partition by sales_date) = 0
then (fix_costs / datepart(day, last_day(sales_date))) * 1.0 / sum(case when country <> 'NL' then 1 else 0 end) over (partition by sales_date)
else (fix_costs / datepart(day, last_day(sales_date))) * (sales_volume / sum(case when country <> 'NL' then sales_volume end) over (partition by sales_date))
end) as apportioned_fix_costs
from sales s
where country <> 'None';
Note: You don't seem to want None in your results so that is just filtered out. Then the rest of the data all seems to be on one data in the month. If it can actually be on multiple data, use date_trunc() in the partition by clause.
For reference, Postgres doesn't support last_day(). You can use the expression:
select extract(day from date_trunc('month', sales_date) + interval '1 month' - interval '1 day')
DB-Fiddle

Is there a way to join the below 2 queries

I'm trying to join the below 2 queries.. though both of the below queries use the same tables, I'm unable to get the correct result..
In this query I'm checking for entries present in table 1 which would satisfy the condition m1.condition is 1, and for that entry a query is made to table 2 where even after 5 minutes there is no entry in table 2,then get the count of that entries.
The date check you see for 30 min is to get all the entries in table which are processed half an hour before.
SELECT count(*) AS TOTALCOUNT,
SELECT TO_CHAR(amount, '$999,999,999,999,999.99') AS TOTALVALUE
from table1 m1
LEFT JOIN table2 m ON m.id=m1.id
where m1.condition='1'
and amount BETWEEN 1000 and 25000
and (m1.DATE <= (select to_char((select systimestamp - interval '0 00:05' day to minute from dual),'dd-MON-yy HH.MI.SS AM TZD') from dual))
and m1.DATE <= (select to_char((select systimestamp - interval '0 00:30' day to minute from dual),'dd-MON-yy HH.MI.SS AM TZD') from dual)
and m1.DATE <= systimestamp
similarly in below query in table 2 there are some conditions.. so based on that I'm performing some actions.
SELECT COALESCE(SUM (CASE when m.f = 'Converted' then 1 else 0 END),0) AS CCOUNT,
COALESCE(SUM (CASE when m.f = 'Do Not Convert' then 1 else 0 END),0) AS NCOUNT,
count(m. id) AS TOTALCOUNT,
TO_CHAR(COALESCE (SUM(CASE when m.f = 'C' then (amount) END),0), '$999,999,999,999,999.99') AS CONVERTED,
TO_CHAR(COALESCE (SUM(CASE when m.f = 'D' then (amount) END),0), '$999,999,999,999,999.99') AS NONCONVERTED,
TO_CHAR(COALESCE (SUM(CASE when m.f <> '0' then (amount) END),0), '$999,999,999,999,999.99') AS TOTAL
FROM table1 ml
JOIN table2 m ON m.id=ml.id
and amount BETWEEN 1000 and 25000
and m1.DATE <= (select to_char((select systimestamp - interval '0 30:00' day to minute from dual),'dd-MON-yy HH.MI.SS AM TZD') from dual)
and m1.DATE < systimestamp;
I have to combine both the above queries.. but I'm unable to do.
The only real difference between filters is that m1.condition = '1', so just add
count(case condition when '1' then 1 end) as condition_1_totalcount,
sum(case condition when '1' then amount end) as condition_1_totalvalue
to your second query. In my short test it looks OK:
-- sample data
with
table1(id, date_, condition) as (
select 1, date '1990-02-19', '1' from dual union all
select 2, date '1990-02-19', '7' from dual union all
select 3, date '1990-02-19', '1' from dual union all
select 4, date '1990-02-19', '1' from dual ),
table2(id, f, amount) as (
select 1, 'C', 3000 from dual union all
select 2, 'D', 3500 from dual union all
select 3, 'D', 4000 from dual union all
select 4, 'D', 5000 from dual )
-- query
select sum (case when m.f = 'Converted' then 1 else 0 end) ccount,
sum (case when m.f = 'Do Not Convert' then 1 else 0 end) as ncount,
count(m.id) as totalcount,
sum(case when m.f = 'C' then (amount) end) as converted,
sum(case when m.f = 'D' then (amount) end) as nonconverted,
sum(case when m.f <> '0' then (amount) end) as total,
count(case condition when '1' then 1 end) as condition_1_totalcount,
sum(case condition when '1' then amount end) as condition_1_totalvalue
from table1 ml
join table2 m on m.id = ml.id
where ml.date_ <= systimestamp - interval '30' minute
and amount between 1000 and 25000
I do not fully understand why is this 5 min part in first query. Rows older than 30 minutes are also older than 5 min, so it is superfluous as pointed in comments. And older than current timestamp. If you need to differentiate values this way you can also place this condition in case whens.