How to compare system month and sales months? - oracle

I want to compare sales months with the system month. if equal get 1 output as new column(last_month) else 0. I tried below oracle query but I am getting a Null value.
SELECT a.agent_id,a.agent_name,a.ivr_registered_district,s.agent_type,s.district,s.province,a.parent_level1_id,a.parent_level1,a.sales_channel,TO_CHAR(TRUNC(a.connection_date, 'MONTH'), 'MON-YYYY') AS MONTHYEAR,
CASE
WHEN TO_CHAR(TRUNC(a.connection_date, 'MONTH'), 'MON-YYYY') = TO_CHAR(ADD_MONTHS(SYSDATE, - 1))
THEN 1
END as last_month
FROM EDW_TGT.FACT_LTE_SALES_CHANNELS a
JOIN SFA.sfa_agent_dtl s
ON a.agent_id = s.agent_id
where a.pre_post = 'LTE-PREPAID' and a.sales_channel in ('BUSINESS PARTNER', 'INSTITUSIONAL', 'REGIONAL TRADE PARTNERS', 'DISTRIBUTOR')
and a.connection_date >= TO_DATE('2020-01-01 00:00:0', 'YYYY-MM-DD HH24:MI:SS')

You don't need to truncate date as oracle provides you functionality to extract (day,month,year) from to_date function.
Your query should be like below.
SELECT a.agent_id,a.agent_name,a.ivr_registered_district,s.agent_type,s.district,s.province,a.parent_level1_id,a.parent_level1,a.sales_channel,TO_CHAR(TRUNC(a.connection_date, 'MONTH'), 'MON-YYYY') AS MONTHYEAR,
CASE
WHEN to_char(to_date(a.connection_date, 'DD-MM-YYYY'), 'Month') = to_char(to_date(sysdate-1, 'DD-MM-YYYY'), 'Month')
THEN 1
Else 0
END as last_month
FROM EDW_TGT.FACT_LTE_SALES_CHANNELS a
JOIN SFA.sfa_agent_dtl s
ON a.agent_id = s.agent_id
where a.pre_post = 'LTE-PREPAID' and a.sales_channel in ('BUSINESS PARTNER', 'INSTITUSIONAL', 'REGIONAL TRADE PARTNERS', 'DISTRIBUTOR')
and a.connection_date >= TO_DATE('2020-01-01 00:00:0', 'YYYY-MM-DD HH24:MI:SS')

Related

This query giving error, While executing this syntax error comes for AS LastYearVolumeBilled

Error comes on AS LastYearVolumeBilled this line how to add two case when in one select statement
select 'R-1' as Year,
(case when SDBM_MONTH_YR = to_number(extract(year from sysdate) || '04')then
round((sum(SDBM_BILLED_UNITS)/avg(sdbm_billing_days))/1000,2)
end )AS CurrentYearVolumeBilled
FROM t_servicedetail_billing
where SDBM_MONTH_YR= to_number(extract(year from sysdate) || '04')
group by SDBM_MONTH_YR ,
(CASE WHEN SDBM_MONTH_YR = to_number( extract(year from add_months(sysdate,-12)) || '04')
THEN round((sum(SDBM_BILLED_UNITS)/avg(sdbm_billing_days))/1000,2)
END)AS LastYearVolumeBilled
FROM t_servicedetail_billing
where SDBM_MONTH_YR= to_number( extract(year from add_months(sysdate,-12)) || '04')
group by SDBM_MONTH_YR;
These are two different queries, so one option might be to treat them as such by using a CTE (as my example shows) or as subqueries.
WITH
t_curr
AS
( SELECT 'R-1' AS year,
(CASE
WHEN sdbm_month_yr =
TO_NUMBER (EXTRACT (YEAR FROM SYSDATE) || '04')
THEN
ROUND (
(SUM (sdbm_billed_units) / AVG (sdbm_billing_days))
/ 1000,
2)
END) AS currentyearvolumebilled
FROM t_servicedetail_billing
WHERE sdbm_month_yr = TO_NUMBER (EXTRACT (YEAR FROM SYSDATE) || '04')
GROUP BY sdbm_month_yr),
t_last
AS
( SELECT 'R-1' AS year,
(CASE
WHEN sdbm_month_yr =
TO_NUMBER (
EXTRACT (YEAR FROM ADD_MONTHS (SYSDATE, -12))
|| '04')
THEN
ROUND (
(SUM (sdbm_billed_units) / AVG (sdbm_billing_days))
/ 1000,
2)
END) AS lastyearvolumebilled
FROM t_servicedetail_billing
WHERE sdbm_month_yr =
TO_NUMBER (
EXTRACT (YEAR FROM ADD_MONTHS (SYSDATE, -12)) || '04')
GROUP BY sdbm_month_yr)
SELECT a.year, a.currentyearvolumebilled, b.lastyearvolumebilled
FROM t_curr a CROSS JOIN t_last b;
How to add more subqueries (simplified):
with
t_curr_r1 as
(select 'R-1' as year, ... from ...),
t_curr_r2 as
(select 'R-2' as year, ... from ...),
t_curr_r3 as
(select 'R-3' as year, ... from ...),
--
t_last_r1
(select 'R-1' as year, ... from ...),
t_last_r2 as
(select 'R-2' as year, ... from ...),
t_last_r3 as
(select 'R-3' as year, ... from ...),
--
select c1.year, c1.currentyearvolumebilled,
c2.currentyearvolumebilled,
c3.currentyearvolumebilled,
...
l1.lastyearvolumebilled,
l2.lastyearvolumebilled,
l3.lastyearvolumebilled,
...
from t_curr_r1 c1 cross join t_curr_r2 c2
cross join t_curr_r3 c3
...
cross join t_last_r1 l1
cross join t_last_r2 l2
cross join t_last_r3 l3
...
You have repeated your query twice. You don't need a case statement cause you have the same condition in where clause. So the correct query might be -
select 'R-1' as Year,
round((sum(SDBM_BILLED_UNITS)/avg(sdbm_billing_days))/1000,2)
END AS CurrentYearVolumeBilled
FROM t_servicedetail_billing
WHERE SDBM_MONTH_YR = to_number(extract(year from sysdate) || '04')

ORACLE Query Count Slow

I'm trying to query my Oracle script on Toad but got slow response, about 4-8 seconds.
The script query is about count, below is mine:
SELECT COUNT(*)
AS TOTALS
FROM(SELECT S.BADGEID_FK, S.SHIFT, S.STATUS, E.BADGEID, E.FIRSTNAME, E.LASTNAME
FROM WA_SEW_TBL_EMP_INFO S, WA_GA_TBL_EMPLOYEES E
WHERE S.BADGEID_FK = E.BADGEID AND S.STATUS = 'Attend' AND S.SHIFT = 'Morning'
AND S.BADGEID_FK NOT IN(SELECT EMPID
FROM WA_SEW_TBL_RESULTS
WHERE TO_CHAR(SYSTEM_DATE, 'YYYY-MM-DD') = '2017-08-30'
AND TO_CHAR(SYSTEM_DATE, 'HH24:MI') >= '07:00'
AND TO_CHAR(SYSTEM_DATE, 'HH24:MI') <= '19:29'))
I tried to add indexing to some column, but there is no effect.
Is there any way to do that query? or any trick?
This part:
WHERE TO_CHAR(SYSTEM_DATE, 'YYYY-MM-DD') = '2017-08-30'
AND TO_CHAR(SYSTEM_DATE, 'HH24:MI') >= '07:00'
AND TO_CHAR(SYSTEM_DATE, 'HH24:MI') <= '19:29'
Would be better rewritten as:
WHERE SYSTEM_DATE between to_date ('2017-08-30 07:00:00', 'YYYY-MM-DD HH24:MI:SS')
and to_date ('2017-08-30 19:29:59', 'YYYY-MM-DD HH24:MI:SS')
That will allow any index on SYSTEM_DATE to be used.
One obvious suspect is your date manipulation in the IN list. You should never, ever use functions around dates - that kills any ability of Oracle to use an index on the date column.
Instead:
where system_date >= to_date('2017-08-30 07:00', 'yyyy-mm-dd hh24:mi')
and system_date < to_date('2017-08-30 19:30', 'yyyy-mm-dd hh24:mi')
(the second inequality is strict, if you want to exclude 7:30pm sharp).
I was able to eliminate most of the subqueries but I'm not sure it will result in the performance gain w/o knowledge of table size and indexes. Posting the execution plan would help us understand where your bottleneck is.
SELECT count(*) as Totals
FROM WA_SEW_TBL_EMP_INFO S
INNER JOIN WA_GA_TBL_EMPLOYEES E
ON S.BADGEID_FK = E.BADGEID
LEFT JOIN WA_SEW_TBL_RESULTS R
ON S.BADGEID_FK =R.EMPID
-- Others already addressed what needs to happen here.
AND TO_CHAR(R.SYSTEM_DATE, 'YYYY-MM-DD') = '2017-08-30'
AND TO_CHAR(R.SYSTEM_DATE,'HH24:MI') >= '07:00'
AND TO_CHAR(R.SYSTEM_DATE,'HH24:MI') <= '19:29'
WHERE S.STATUS = 'Attend'
AND S.SHIFT = 'Morning'
AND R.EmpID is null

How to query for a specific day of the month in Oracle

Trying to automate a query that will pull data for the current month where the day of the month (in the date field) is >= the 15th. Is this possible? If so, what is the syntax to achieve this?
I want to be able to run this query each month without having to change anything. So in May, it would automatically pull any item where the date was >= 5/15/16. In June, it would pull items where the date was >= 6/15/16. And so on.....
Any help in this would be greatly appreciated. Thanks
This will allow you to use any indexes you have on your date_field column:
SELECT *
FROM table_name
WHERE date_field >= TRUNC( SYSDATE, 'MM' ) + INTERVAL '14' DAY
AND date_field < ADD_MONTHS( TRUNC( SYSDATE, 'MM' ), 1 );
If your date/time fields are of type timestamp you can do
select x from <your_table>
where EXTRACT(DAY from <timestamp field>) >=15
and EXTRACT(MONTH from <timestamp field>) = EXTRACT(MONTH FROM CURRENT_TIMESTAMP)
and EXTRACT(YEAR from <timestamp field>) = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);
I think what you're after is something like:
with sample_data as (select 1 id, to_date('01/06/2016', 'dd/mm/yyyy') dt from dual union all
select 2 id, to_date('10/06/2016', 'dd/mm/yyyy') dt from dual union all
select 3 id, to_date('14/06/2016', 'dd/mm/yyyy') dt from dual union all
select 4 id, to_date('15/06/2016', 'dd/mm/yyyy') dt from dual union all
select 5 id, to_date('16/06/2016', 'dd/mm/yyyy') dt from dual union all
select 6 id, to_date('30/06/2016', 'dd/mm/yyyy') dt from dual union all
select 7 id, to_date('01/07/2016', 'dd/mm/yyyy') dt from dual)
select *
from sample_data
where dt >= trunc(sysdate, 'mm') + 14
and dt < last_day(trunc(sysdate)) + 1;
ID DT
---------- ----------
4 15/06/2016
5 16/06/2016
6 30/06/2016
(If you wanted rows with any date greater than the 15th of the current month, then remove the last predicate in the where clause.)

Excluding rows from outer join

I am trying to extract rows from a table to gain the start and end time for events, these are held in a one to many table relationship so that for each instanceid in the master table you can have a number of entryids in the child. I have successfully written the below query that extracts the required data converting epoch timestamps, but am getting rows with NULL values. I can see that to exclude these I need to only select rows from table_a where the status value reflect 1 or 6, but am not sure of syntax for achieving this, I have tried combos of bold highlighted line below to no avail.
SELECT a.summary
to_char(date '1970-01-01' + b.create_date/86400, 'DD Mon YYYY HH24:MI:SS') as start_date,
to_char(date '1970-01-01' + c.create_date/86400, 'DD Mon YYYY HH24:MI:SS') as completed_date,
to_char (TRUNC (SYSDATE) + NUMTODSINTERVAL ((c.create_date - b.create_date), 'second'), 'hh24:mi:ss') as Elapse_Time,
a.status
FROM o2_hpov_casecreation a
LEFT OUTER JOIN o2_hpov_casecreation_audit b
ON (a.instanceid = c.entryid
AND B.action= 'Queueing Simulation phase on SYS:Action')
LEFT OUTER JOIN o2_hpov_casecreation_audit c
ON (a.instanceid = c.entryid
AND c.action = 'Notifications completed')
AND a.status IN (2,6)
You need to add your filter criteria to the where clause
below is a corrected version of your query
SELECT a.summary
to_char(date '1970-01-01' + b.create_date/86400, 'DD Mon YYYY HH24:MI:SS') as start_date,
to_char(date '1970-01-01' + c.create_date/86400, 'DD Mon YYYY HH24:MI:SS') as completed_date,
to_char (TRUNC (SYSDATE) + NUMTODSINTERVAL ((c.create_date - b.create_date), 'second'), 'hh24:mi:ss') as Elapse_Time,
a.status
FROM o2_hpov_casecreation a
LEFT OUTER JOIN o2_hpov_casecreation_audit b
ON (a.instanceid = c.entryid
AND B.action= 'Queueing Simulation phase on SYS:Action')
LEFT OUTER JOIN o2_hpov_casecreation_audit c
ON (a.instanceid = c.entryid
AND c.action = 'Notifications completed')
WHERE a.status IN (2,6)

Count the no of saturdays and sundays in date range - oracle [duplicate]

This question already has answers here:
Number of fridays between two dates
(7 answers)
Closed 8 years ago.
I have two parameters(start_Date,end_Date) from table1
I'm trying to count no of saturdays and sundays in a date range
star_Date=8/20/2014 13:52
end_Date=8/28/2014 13:52
And result should be like this
Start_Date end_date No_of_leaves
8/20/2014 13:52 8/28/2014 13:52 2
Update Section
SELECT retouch_req_time,retouch_submit_time,(
SELECT Count(*) FROM (SELECT To_char(start_date + ( LEVEL - 1 ), 'fmday') dt
FROM (WITH t AS (SELECT To_date (retouch_req_time, 'MM/DD/YYYY HH24:MI') start_date, To_date (retouch_submit_time, 'MM/DD/YYYY HH24:MI') end_date FROM TT))
CONNECT BY LEVEL <= end_date - start_date + 1) WHERE dt IN ('friday','saturday')) as worked_hours
FROM TT
You can try using hierarchical queries
WITH t
AS (SELECT To_date ('8/20/2014 13:52', 'MM/DD/YYYY HH24:MI') start_date,
To_date ('8/28/2014 13:52', 'MM/DD/YYYY HH24:MI') end_date
FROM dual)
SELECT Count(*)
FROM (SELECT To_char(start_date + ( LEVEL - 1 ), 'fmday') dt
FROM t
CONNECT BY LEVEL <= end_date - start_date + 1)
WHERE dt IN ( 'friday', 'saturday' );
RESULT
------
2
* The dates are listed by expanding the range.
* The TO_CHAR function is used to obtain the weekday
* Count everthing which is a friday or saturday
If you want to find the day wise count, then you can try
SELECT To_char(dat, 'DY'),
Count(*)
FROM (SELECT To_date ('8/20/2014 13:52', 'MM/DD/YYYY HH24:MI')
+ num dat
FROM (SELECT LEVEL - 1 num
FROM dual
CONNECT BY LEVEL <= Abs(To_date ('8/20/2014 13:52',
'MM/DD/YYYY HH24:MI') -
To_date (
'8/28/2014 13:52'
,
'MM/DD/YYYY HH24:MI')) - 1
))
WHERE To_char(dat, 'DY') IN ( 'FRI', 'SAT' )
GROUP BY To_char(dat, 'DY');
RESULTS
TO_CHAR(DAT,'DY') COUNT(*)
----------------- --------
FRI 1
SAT 1
You can calculate the number of saturdays and sundays like this:
with t(d) as (
select sysdate + level from dual connect by rownum < 10
)
select count(case when trim(to_char(d, 'DAY')) in ('SATURDAY', 'SUNDAY') then 1 end) cnt from t
CNT
---
2
If you don't have a range of dates then:
with t(a, b) as (
select sysdate a, sysdate + 10 b from dual connect by rownum < 10
), t2(d) as (
select a + level - 1 from t connect by rownum <= b - a
)
select count(case when trim(to_char(d, 'DAY')) in ('SATURDAY', 'SUNDAY') then 1 end) cnt from t2
CNT
---
2

Resources