SQL query to get count based differnt condition - sql

Description of table columns -
TYPE : VARCHAR
STATUS : VARCHAR
ORDER_DATE : TIMESTAMP WITH TIMEZONE
Please find the below table structure and required output.
In the required result -
0TO30DAYS : Count of Type for previous 30 days
30TO60DAYS : Count of Type for previous 31 to 60 Days
60TO90DAYS : Count of type for 61 to 90 Days
Please note that I'm using Oracle DB unable to create three different count columns as per the different date range. Please let me know how to create SQL for the same in ORACLE.

count ignores null, so you could count a case expression with your logic:
SELECT type,
COUNT(CASE WHEN day_diff BETWEEN 0 AND 31 THEN 1 ELSE NULL END)
AS "0TO30DAYS",
COUNT(CASE WHEN day_diff BETWEEN 31 AND 61 THEN 1 ELSE NULL END)
AS "30TO60DAYS",
COUNT(CASE WHEN day_diff BETWEEN 61 AND 91 THEN 1 ELSE NULL END)
AS "60TO90DAYS"
FROM (SELECT type, CAST (order_date AS DATE) - SYSDATE AS day_diff
FROM my_table)
GROUP BY type

SELECT TYPE,
CASE
WHEN order_date >= (SYSDATE - 30) AND order_date < SYSDATE THEN
COUNT(TYPE)
END AS count30,
CASE
WHEN order_date >= (SYSDATE - 60) AND order_date < (SYSDATE - 30) THEN
COUNT(TYPE)
END AS count60,
CASE
WHEN order_date >= (SYSDATE - 90) AND order_date < (SYSDATE - 60) THEN
COUNT(TYPE)
END AS count90
FROM TABLE
GROUP BY TYPE, order_date

Related

Group by date intervall Oracle

I want to retrieve sum of weight data from a table over a whole month.
what I need help with is that I want to group the result into 2 parts
sum of 1-15 of the month
and second line 16-31 of the month.
SELECT(SUM(B.SCALE_WEIGHT) FROM TRACKING.DATALOG_TAB B WHERE B.MATERIALID= 1 AND B.SCALE_EVENTDATE BETWEEN TO_DATE(TRUNC(TO_DATE('2020-10-1', 'YYYY-MM-DD'),'MONTH')) AND TO_DATE(TRUNC(TO_DATE('2020-10-1', 'YYYY-MM-DD'), 'MONTH')+30)
GROUP BY(somthing like this - 1-15 and 16-31)
Here is one option:
select
1 + floor(extract(day from scale_eventdate) / 16) as fortnight,
sum(b.scale_weight) as sum_scale_weight
from tracking.datalog_tab b
where
materialid = 1
and scale_eventdate >= date '2020-10-01'
and scale_eventdate < date '2020-11-01'
group by 1 + floor(extract(day from scale_eventdate) / 16)
This extracts the day number from the date, and then use artithmetics: every day from the 1 to to the 15th of the month included goes to fortnight number 1, and everything afterwards goes to bucket 2.
We could also do this with to_char() and a case expression, which is somewhat more expressive:
select
case when to_char(scale_eventdate, 'dd') <= '15' then 1 else 2 end as fortnight,
sum(b.scale_weight) as sum_scale_weight
from tracking.datalog_tab b
where
materialid = 1
and scale_eventdate >= date '2020-10-01'
and scale_eventdate < date '2020-11-01'
group by case when to_char(scale_eventdate, 'dd') <= '15' then 1 else 2 end
Note that I changed the date filtering logic to use standard date literals, which makes the query shorter and more readable.

Oracle SQL - How to retrieve the ID Count difference between today vs yesterday

I have a table that captures when a customer purchases a product. It captures a unique purchase id along with a timestamp of when the purchase was made.
I want to be able to query, the difference between how many purchases were taken today vs yesterday?
Not sure how to query this on oracle?
You can use conditional aggregation:
select sum(case when trunc(datecol) = trunc(sysdate - 1) then 1 else 0 end) as num_yesterday,
sum(case when trunc(datecol) = trunc(sysdate) then 1 else 0 end) as num_today,
sum(case when trunc(datecol) = trunc(sysdate) then 1
when trunc(datecol) = trunc(sysdate - 1) then -1
end) as diff
from t
where datecol >= trunc(sysdate - 1);
you can use the Group function to grouping the purchase day with timestamp information and count the purchase id.
select trunc(purchase_ts) Day, count(purchase_id) Count
from purchase
group by trunc(purchase_ts)
order by 1
Using TRUNC on the column will prevent Oracle from using an index on that column (instead you would need a separate function-based index); instead use a CASE statement to test whether the date is between the start of the day and the start of the next day and then COUNT the values between those ranges:
SELECT COUNT(
CASE
WHEN TRUNC( SYSDATE ) - INTERVAL '1' DAY <= your_date_column
AND your_date_coumn < TRUNC( SYSDATE )
THEN 1
END
) AS count_for_yesterday,
COUNT(
CASE
WHEN TRUNC( SYSDATE ) <= your_date_column
AND your_date_coumn < TRUNC( SYSDATE ) + INTERVAL '1' DAY
THEN 1
END
) AS count_for_today
FROM your_table
WHERE TRUNC( SYSDATE ) - INTERVAL '1' DAY <= your_date_column
AND your_date_coumn < TRUNC( SYSDATE ) + INTERVAL '1' DAY

SQL ORACLE - Extract data with some properties added in the last 180 days

The table SELL_TABLE has these columns:
LEGACY_ID
PRODUCT_ID
CUSTOMER_ID
DATE
SOLD
I have to extract all the rows ordered by CUSTOMER_ID where SOLDis > 1 and inserted in the last 180 days.
The DATE column is defined as VARCHAR, so I need to transform its content to a datetime first.
How can I do that?
This is how I wrote the query:
select CUSTOMER_ID as Customer, PRODUCT_ID as Product
from SELL_TABLE
where SOLD > 0 and DATE >= DATEADD(day, -180, getdate())
group by CUSTOMER_ID, PRODUCT_ID
order by CUSTOMER_ID;
You may need a where condition with to_date and sysdate like the following:
where to_date(yourDateColumn, 'yyyymmdd') >= trunc(sysdate) - 180
and ...
You can use
TO_DATE
function to convert your varchar column to Date type.
Also, you can replace the
DATEADD
function with simple action:
trunc(sysdate) >= trunc (sysdate - 180)

How to get last month's date from specific date in postgresql

I have a max date in my query and If the max date is current month then I want always get previous month’s date. How can I do that?
For example, today is 20160825. If the max date is 20160801 then I want to get 20160701. But, if the max date is 20160501 then I just want to get without changes - 20160501.
SELECT
DEFN_DK,
MAX(SNAPSHOT_MTH)
FROM myTable
WHERE TOT_AMT >0
GROUP BY DEFN_DK
Since your SNAPSHOT_MTH column is an integer (why?) you can not use any of the otherwise very useful timestamp functions. So it's back to integer math, creating a "month" from your snapshot "date" through integer division by 100. This can be compared to CURRENT_DATE by converting that to a string and then casting it to an integer. Going back 1 month similarly requires some math. Not entirely efficient, but here goes:
SELECT DEFN_DK,
CASE max(SNAPSHOT_MTH) / 100
WHEN tochar(CURRENT_DATE, 'YYYYMM')::int THEN
((max(SNAPSHOT_MTH) / 100) - 1) * 100 + 1
-- or max(SNAPSHOT_MTH) - 100, if you know it always ends in 01
ELSE max(SNAPSHOT_MTH)
END AS SNAPSHOT_MTH
FROM myTable
WHERE TOT_AMT > 0
GROUP BY DEFN_DK;
select
defn_dk,
case max(snapshot_mth)
when date_trunc('month', current_date) then max(snapshot_mth) - interval '1 month'
else max(snapshot_mth)
end
from mytable
where tot_amt >0
group by defn_dk
show this, two examples:
select
case when date_trunc('month',dd) = date_trunc('month',now())
then dd - interval'1 month' else date_trunc('day',dd) end
from
(
select '2016-08-04'::date as dd
) d;
and
select
case when date_trunc('month',dd) = date_trunc('month',now())
then dd - interval'1 month' else date_trunc('day',dd) end
from
(
select '2016-05-04'::date as dd
) d;

SQL Server - Dividing one column by another in a SELECT query

I am seeking to make some Week On Week comparisons in a SELECT query.
The basic code will select distinct areas in the leftmost column, then the following code:
SELECT
(CASE WHEN TIMESTAMP >= GETDATE() -7 AND TIMESTAMP < GETDATE()
THEN ORDER_ID
ELSE NULL
END) AS THISWEEK
SELECT
(CASE WHEN TIMESTAMP >= GETDATE() -14 AND TIMESTAMP < GETDATE() -7
THEN ORDER_ID
ELSE NULL
END) AS LASTWEEK
I'd really like to be able to have (THISWEEK / LASTWEEK) - 1 (Like I would in excel)
Is this possible?
Is this what you want?
select (thisweek / lastweek) - 1
from (SELECT (CASE WHEN TIMESTAMP >= GETDATE() -7 AND TIMESTAMP < GETDATE()
THEN ORDER_ID
END) AS THISWEEK,
(CASE WHEN TIMESTAMP >= GETDATE() -14 AND TIMESTAMP < GETDATE() -7
THEN ORDER_ID
END) AS LASTWEEK
from . . .
) t
It defines the variables in a subquery and then ues them. Note that there is not any performance penalty for this; SQL Server does not "instantiate" the subquery.