find the employee count based on hire date In Oracle - sql

I want to find out the employee count who are all joined between January month to December month for the year(2020). suppose if any employee is not joined on any particular month,the count should display as 0.
Empno Ename Hiredate deptno
101 ram 11-Jan-20 10
102 kumar 07-Mar-20 10
103 Raja 06-Oct-20 20
104 Sasi 16-Dec-20 20
105 manoj 19-Dec-20 10
Excepted Output
Count Hiredate_Month
1 Jan
0 Feb
1 Mar
0 Apr
0 May
0 Jun
0 Jul
0 Aug
0 Sep
1 Oct
0 Nov
2 Dec
I tried below things.
create table emp_details(empno number,ename varchar2(22),hiredate date,deptno number);
insert into emp_details values(101,'ram','11-jan-2020',10);
insert into emp_details values(102,'kumar','07-mar-2020',10);
insert into emp_details values(103,'raja','06-oct-2020',20);
insert into emp_details values(104,'sasi','16-dec-2020',20);
insert into emp_details values(105,'manoj','19-dec-2020',10);
select count(*),to_char(hiredate,'mon') from emp_details group by
to_char(hiredate,'mon')
Above query is not displaying count 0 for the months whose employee is not joined.

In Scott's sample schema, there's the EMP table:
SQL> select ename, hiredate
2 from emp
3 order by to_char(hiredate, 'mm');
ENAME HIREDATE
---------- --------
ADAMS 12.01.83 --> Adams and Miller
MILLER 23.01.82 --> were hired in January
ALLEN 20.02.81
WARD 22.02.81
--> nobody was hired in March
JONES 02.04.81 --> Jones was hired in April
BLAKE 01.05.81
CLARK 09.06.81
TURNER 08.09.81
MARTIN 28.09.81
KING 17.11.81
SCOTT 09.12.82
SMITH 17.12.80
JAMES 03.12.81
FORD 03.12.81
14 rows selected.
In order to get result you want, you need a calendar - separate table which contains all months in a year because table with employees doesn't contain all months (see above - nobody was hired in e.g. March).
Then you'd outer join that calendar with the original table, count number of employees and - that's it:
SQL> with calendar as
2 (select lpad(level, 2, '0') mon
3 from dual
4 connect by level <= 12
5 )
6 select to_char(to_date(c.mon, 'mm'), 'Mon', 'nls_date_language = english') hiredate_month,
7 count(e.empno) cnt
8 from calendar c left join emp e on to_char(e.hiredate, 'mm') = c.mon
9 group by c.mon
10 order by c.mon;
HIREDATE_MON CNT
------------ ----------
Jan 2
Feb 2
Mar 0
Apr 1
May 1
Jun 1
Jul 0
Aug 0
Sep 2
Oct 0
Nov 1
Dec 4
12 rows selected.
SQL>

Related

list values ​that are duplicated more than 4 times

I am making a join between 2 tables, where they bring me number_phone that have a relationship and I bring the times that these are repeated, however, I am trying to make a condition to the count, so that it only lists those that are repeated more than 4 times, I tried with having account and it brings me the counter all in null.
It is worth mentioning that I did not occupy group by for the count because it brought me wrong values.
SELECT
REPLACE(REPLACE(t.id_contrato,'0999',''),'0998','')as contrato ,
t.num_telefono,
conc.valor_actual,
(
SELECT COUNT('x')
FROM TBL_TELEFONO ct
WHERE ct.num_telefono = t.num_telefono
AND ct.origen_tel='TELEFONO CONTRATO'
-- HAVING COUNT(*) > 4
) as counter
FROM TBL_TELEFONO t
INNER JOIN CAM_TBL_ALERTA_CONCENTRADO conc ON t.num_telefono = conc.valor_actual
WHERE id_contrato IS NOT NULL
AND id_contrato NOT IN ('N/A')
ORDER BY 4 DESC
How can I list only those that are repeated more than 4 times?
I don't like debugging code with no sample data, so I'll try to illustrate it on Scott's sample EMP table. "Jobs" will act like your "telephone numbers".
SQL> select deptno, ename, job
2 from emp
3 order by job;
DEPTNO ENAME JOB
---------- ---------- ---------
20 SCOTT ANALYST --> 2 analysts
20 FORD ANALYST
10 MILLER CLERK --> 4 clerks
30 JAMES CLERK
20 SMITH CLERK
20 ADAMS CLERK
30 BLAKE MANAGER --> 3 managers
20 JONES MANAGER
10 CLARK MANAGER
10 KING PRESIDENT --> 1 president
30 TURNER SALESMAN --> 4 salesmen
30 MARTIN SALESMAN
30 WARD SALESMAN
30 ALLEN SALESMAN
14 rows selected.
SQL>
According to that, we'd like to fetch all clerks and salesmen as there are 4 (or more) of them.
Instead of count aggregate function, use count in its analytic form:
SQL> select deptno, ename, job,
2 count(*) over (partition by job) cnt
3 from emp
4 order by job;
DEPTNO ENAME JOB CNT
---------- ---------- --------- ----------
20 SCOTT ANALYST 2
20 FORD ANALYST 2
10 MILLER CLERK 4
30 JAMES CLERK 4
20 SMITH CLERK 4
20 ADAMS CLERK 4
30 BLAKE MANAGER 3
20 JONES MANAGER 3
10 CLARK MANAGER 3
10 KING PRESIDENT 1
30 TURNER SALESMAN 4
30 MARTIN SALESMAN 4
30 WARD SALESMAN 4
30 ALLEN SALESMAN 4
14 rows selected.
SQL>
Now things become easier: use that query as a CTE (or a subquery), and apply where clause:
SQL> with temp as
2 (select deptno, ename, job,
3 count(*) over (partition by job) cnt
4 from emp
5 )
6 select deptno, ename, job
7 from temp
8 where cnt >= 4
9 order by job;
DEPTNO ENAME JOB
---------- ---------- ---------
10 MILLER CLERK
30 JAMES CLERK
20 SMITH CLERK
20 ADAMS CLERK
30 TURNER SALESMAN
30 MARTIN SALESMAN
30 WARD SALESMAN
30 ALLEN SALESMAN
8 rows selected.
SQL>
Applied to your query (again, can't test it without any sample data):
with temp as
(select
replace(replace(t.id_contrato,'0999',''),'0998','')as contrato ,
t.num_telefono,
conc.valor_actual,
count(*) over (partition by t.num_telefono) as counter
from tbl_telefono t
inner join cam_tbl_alerta_concentrado conc on t.num_telefono = conc.valor_actual
where id_contrato is not null
and id_contrato not in ('N/A')
)
select contrato, num_telefono, valor_actual
from temp
where counter >= 4;
Join to the selection that have more than 4
SELECT
REPLACE(REPLACE(t.id_contrato,'0999',''),'0998','')as contrato ,
t.num_telefono,
conc.valor_actual,
ct.counter
FROM TBL_TELEFONO t
INNER JOIN (
SELECT num_telefono, COUNT(*) AS counter
FROM TBL_TELEFONO
WHERE origen_tel='TELEFONO CONTRATO'
GROUP BY num_telefono
HAVING COUNT(*) > 4
) ct
ON ct.num_telefono = t.num_telefono
INNER JOIN CAM_TBL_ALERTA_CONCENTRADO conc
ON t.num_telefono = conc.valor_actual
WHERE id_contrato IS NOT NULL
AND id_contrato NOT IN ('N/A')
ORDER BY ct.counter DESC
Wrap the query in another to return only where count > 4
select *
from (
<your query, but without order by>
) x
where count > 4
order by count desc

Convert String to char in oracle

Hi i have the following data '1,2,3' and i need to convert this into this '1','2','3' that i will use in this
Select * from dual where to_chat(month) in ('1','2','3')
i cannot use query straight like that because of the quater
Quater no. Month
1 1,2,3
2 4,5,6
...
so i must use case like this but case statement return on format like this '1','2','3'
Select * from dual
where to_chat(month) in (
select
case quarter
when 1 then '1','2','3'
when 2 then '4','5','6'
end
from dual )
input
'1,2,3'
expected output
'1','2','3'
You can use regexp_like():
where regexp_like(<whatever>, replace('1,2,3', ',', '|'))
Putting single quotes in the string still won't enable you to do what you want with like. It will still be a single string, but one that has single quotes and commas in it.
How about such an approach? Example is based on Scott's EMP table. I'd like to fetch employees which were hired in certain months.
Sample data:
SQL> select deptno, ename, job, hiredate, to_char(hiredate, 'mm') mon from emp order by mon;
DEPTNO ENAME JOB HIREDATE MO
---------- ---------- --------- ---------- --
20 ADAMS CLERK 12.01.1983 01
10 MILLER CLERK 23.01.1982 01
30 ALLEN SALESMAN 20.02.1981 02 -- suppose I want to select employees
30 WARD SALESMAN 22.02.1981 02 -- hired in February,
20 JONES MANAGER 02.04.1981 04 -- April and
30 BLAKE MANAGER 01.05.1981 05 -- May
10 CLARK MANAGER 09.06.1981 06
30 TURNER SALESMAN 08.09.1981 09
30 MARTIN SALESMAN 28.09.1981 09
10 KING PRESIDENT 17.11.1981 11
20 SCOTT ANALYST 09.12.1982 12
20 SMITH CLERK 17.12.1980 12
30 JAMES CLERK 03.12.1981 12
20 FORD ANALYST 03.12.1981 12
14 rows selected.
Query - which splits input search string into rows (so that you could use it in IN clause) would then be:
SQL> with src as
2 (select &par_month src_month from dual)
3 select deptno, ename, job, hiredate
4 from emp
5 where to_number(to_char(hiredate, 'mm')) in
6 (select regexp_substr(src_month, '[^,]+', 1, level)
7 from src
8 connect by level <= regexp_count(src_month, ',') + 1
9 )
10 order by to_char(hiredate, 'mm');
Enter value for par_month: '2,4,5'
DEPTNO ENAME JOB HIREDATE
---------- ---------- --------- ----------
30 ALLEN SALESMAN 20.02.1981
30 WARD SALESMAN 22.02.1981
20 JONES MANAGER 02.04.1981
30 BLAKE MANAGER 01.05.1981
SQL>

How can i write hired the same month employees and order?

Sql, which gives the number of employees hired in the same month (or year) grouped and sequentially on date basis.
I tried to write this code, but i didn't find same hired and order.
SELECT hire_date,COUNT(hire_date)
FROM employees
GROUP BY hire_date;
This is how I understood the question.
Sample data:
SQL> select ename, hiredate from emp order by hiredate;
ENAME HIREDATE
---------- ----------
SMITH 17_12_1980
ALLEN 20_02_1981
WARD 22_02_1981
JONES 02_04_1981
BLAKE 01_05_1981
CLARK 09_06_1981
TURNER 08_09_1981
MARTIN 28_09_1981
KING 17_11_1981
JAMES 03_12_1981
FORD 03_12_1981
MILLER 23_01_1982
SCOTT 09_12_1982
ADAMS 12_01_1983
14 rows selected.
Employed in the same month:
SQL> select to_char(hiredate, 'mm.yyyy') hire_month,
2 count(*)
3 from emp
4 group by to_char(hiredate, 'mm.yyyy')
5 order by 1;
HIRE_MO COUNT(*)
------- ----------
01.1982 1
01.1983 1
02.1981 2
04.1981 1
05.1981 1
06.1981 1
09.1981 2
11.1981 1
12.1980 1
12.1981 2
12.1982 1
11 rows selected.
SQL>
Hired in the same year:
SQL> select extract(year from hiredate) hire_year,
2 count(*)
3 from emp
4 group by extract(year from hiredate)
5 order by 1;
HIRE_YEAR COUNT(*)
---------- ----------
1980 1
1981 10
1982 2
1983 1
SQL>

How to get MAX/MIN function for each month in my data set?

I'm needing to provide usage data and need to summarize it by month.
In my code I have it only looking at JAN of 2018 so find the Max and Min based on the current data set is pretty straight forward. If I was to expand it for all of 2018 I'd currently show the MAX and MIN for the entire year.
SELECT DISTINCT
bi_vwn_co_acct,
bi_consumer_view_1.bi_format_name,
bi_srv_loc.bi_city,
bi_srv_loc.bi_st,
bi_srv_loc.bi_x_coord,
bi_srv_loc.bi_y_coord,
bi_interval_rdgs.bi_mtr_nbr,
MAX (bi_interval_rdgs.bi_rdg),
MIN (bi_interval_rdgs.bi_rdg),
(MAX (bi_interval_rdgs.bi_rdg) - MIN (bi_interval_rdgs.bi_rdg))
AS monthusage
FROM bi_srv_loc
INNER JOIN bi_srv_link
ON bi_srv_loc.bi_srv_loc_nbr = bi_srv_link.bi_srv_loc_nbr
INNER JOIN bi_type_service
ON bi_srv_link.bi_srv_loc_nbr = bi_type_service.bi_srv_loc_nbr
INNER JOIN bi_consumer_view_1
ON bi_type_service.bi_acct = bi_consumer_view_1.bi_vwn_co_acct
INNER JOIN bi_interval_rdgs
ON bi_srv_link.bi_mtr_nbr = bi_interval_rdgs.bi_mtr_nbr
WHERE bi_interval_rdg_dt_tm >= '01-JAN-2018'
AND bi_interval_rdg_dt_tm <= '31-JAN-2018'
AND bi_type_service.bi_srv_stat_cd IN ('1',
'7',
'18',
'21',
'22',
'30')
GROUP BY bi_consumer_view_1.bi_vwn_co_acct,
bi_consumer_view_1.bi_format_name,
bi_srv_loc.bi_x_coord,
bi_srv_loc.bi_y_coord,
bi_interval_rdgs.bi_mtr_nbr,
bi_srv_loc.bi_city,
bi_srv_loc.bi_st
I'm hoping to get a list of data that looks something like this:
ACCT1 JAN MONTHUSAGE: 10
ACCT1 FEB MONTHUSAGE: 13
ACCT1 MAR MONTHUSAGE: 12
...
ACCT2 JAN MONTHUSAGE: 23
ACCT2 FEB MONTHUSAGE: 18
There's obviously more fields shown in my code but in general this is what I'm after. Somehow I need to be able to go through a given date range and section it off by month. Any help or guidance would be greatly appreciated!
Tweak your query to also GROUP BY MONTH(BI_INTERVAL_RDG_DT_TM), YEAR(BI_INTERVAL_RDG_DT_TM )
I'm not sure I understood which column (out of all those) represents data value, so - here's an example based on Scott's sample schema which might give you idea - extract month and year information out of the date column (for example, by using TO_CHAR function) and include it into the GROUP BY clause.
SQL> select to_char(e.hiredate, 'yyyymm') mon,
2 min(e.sal) minsal,
3 max(e.sal) maxsal
4 from emp e
5 group by to_char(e.hiredate, 'yyyymm')
6 order by to_char(e.hiredate, 'yyyymm');
MON MINSAL MAXSAL
------ ---------- ----------
198012 800 800
198102 1250 1600
198104 2975 2975
198105 2850 2850
198106 2450 2450
198109 1250 1500
198111 5000 5000
198112 950 3000
198201 1300 1300
198212 3000 3000
198301 1100 1100
11 rows selected.
SQL>

aggregate a few rows and display in oracle

I have a table ZXC
select NAME, MONTH, YEAR, DEPT, MONTHVAL, YEARVAL from ZXC
the column MONTHVAL has some values. I want to aggregate some rows based on the combination of name, dept and month, and display the aggregated value in YEARVAL column.
for example, if i have the table
Name Month Year Dept Monthval Yearval
BLAKE Jan 2011 100 124.542 0
KING Feb 2011 200 234.542 0
KING Jan 2011 200 27764.464 0
BLAKE March 2011 100 0 0
BLAKE Feb 2011 400 0 0
SCOTT Jan 2011 500 24564.464 0
KING March 2011 200 1265.542 0
KING April 2011 200 1065.542 0
then i want to see the result as
Name Month Year Dept Monthval Yearval
BLAKE Jan 2011 100 124.542 124.542
KING Jan 2011 200 27764.464 27764.464
SCOTT Jan 2011 500 24564.464 24564.464
KING Feb 2011 200 234.542 27999.006
BLAKE Feb 2011 100 0 124.542
KING March 2011 200 1265.542 29264.548
BLAKE March 2011 100 0 124.542
KING April 2011 200 1065.542 30330.09
What about this:
SELECT name
, dept
, year
, SUM( monthval ) yearval
FROM zxc
GROUP BY name
, dept
, year;
This would produce a total of monthly values for each year. I am not really sure if this is
what you needed, but looks like it to me.
You can make it even fancier by using ROLLUP() or CUBE() functions in GROUP BY functions (multiple level of aggregations).
Sounds like:
select NAME,
MONTH,
YEAR,
DEPT,
MONTHVAL,
SUM(MONTHVAL) OVER (PARTITION BY YEAR) YEARVAL
from ZXC
Based on your output, it seems like you want a running total for every person. Basically, the following query shows a general solution for this:
SELECT
Name,
Month,
Year,
Dept,
Monthval,
SUM(Monthval) OVER (PARTITION BY Name, Dept ORDER BY Year, Month) AS Yearval
FROM ZXC
But there might be a problem with ordering by Month, because the months seems to be stored as names in your table, not as numbers. I would then change the above like this:
SELECT
Name,
Month,
Year,
Dept,
Monthval,
SUM(Monthval) OVER (
PARTITION BY Name, Dept
ORDER BY TO_DATE(Year || '-' || SUBSTR(Month, 1, 3), '-01', 'YYYY-MON-DD')
) AS Yearval
FROM ZXC