Average call volumes between times , total for months - sql

Table Calls c
CALL_ID | CALL_START | CONTACT_ID | CALL_TYPE
--------------------------------------------------
2 | 25/11/2010 11:28:16 | 850 | I
3 | 25/11/2010 11:28:57 | 850 | I
5 | 29/11/2010 10:18:44 | 848 | I
Table Contacts ct
CONTACT_ID | COMPANY_ID | RECORD_STATUS
-----------------------------------
1 | 1 | A
19 | 2 | A
20 | 3 | A
21 | 4 | A
22 | 5 | A
I want to extract the number of Incoming and Outgoing calls per month
For one particular Company_id and for all the others.
I also need to have the average number of calls between 0700 and 1500 / 1500 and 2200 / 2200 0700
All starts from October 2016 and I have a list of operator's ID to include...
select
extract(year from c.call_start) as MyYear,
extract(month from c.call_start) as MyMonth,
count(case when call_type='I' and ct.Company_id not like 391 then 1 else null end) as Incoming_Main,
count(case when call_type='O' and ct.Company_id not like 391 then 1 else null end) as Outgoing_Main,
count(case when call_type='I' and ct.Company_id = 391 then 1 else null end) as Incoming_SMG,
count(case when call_type='O' and ct.Company_id = 391 then 1 else null end) as Outgoing_SMG,
SUM(CASE WHEN CAST(c.CALL_START AS TIME) BETWEEN '07:00:00' and '15:00:00' and ct.company_id=391 THEN 1 ELSE 0 END)/31 Am391,
SUM(CASE WHEN CAST(c.CALL_START AS TIME) BETWEEN '07:00:00' and '15:00:00' and ct.company_id not like 391 ELSE 0 END)/31 AmMAIN,
SUM(CASE WHEN CAST(c.CALL_START AS TIME) BETWEEN '15:00:00' and '22:00:00' and ct.company_id =391 THEN 1 ELSE 0 END)/31 PM391,
SUM(CASE WHEN CAST(c.CALL_START AS TIME) BETWEEN '15:00:00' and '22:00:00' and ct.company_id=391 THEN 1 ELSE 0 END)/31 PmMAIN,
SUM(CASE WHEN CAST(c.CALL_START AS TIME) BETWEEN '07:00:00' and '15:00:00' and ct.company_id=391 THEN 1 ELSE 0 END)/31 Am391,
SUM(CASE WHEN CAST(c.CALL_START AS TIME) BETWEEN '07:00:00' and '15:00:00' and ct.company_id=391 THEN 1 ELSE 0 END)/31 Am391,
from
CALLS c
left outer join CONTACTS ct on c.CONTACT_ID= ct.CONTACT_ID
where ct.RECORD_STATUS='A'
and c.OPERATOR_ID in (1,19,22)
and c.call_start >='2016/10/01

Related

DB2/SQL aggregates with preceeding weekdays

I have a query that currently gets daily records against a weekly number from a prepopulated table:
SELECT Employee,
sum(case when category = 'Shirts' then daily_total else 0 end) as Shirts_DAILY,
sum(case when category = 'Shirts' then weekly_quota else 0 end) as Shirts_QUOTA, -- this is a static column, this number is the same for every record
sum(case when category = 'Shoes' then daily_total else 0 end) as Shoes_DAILY,
sum(case when category = 'Shoes' then weekly_quota else 0 end) as Shoes_QUOTA, -- this is a static column, this number is the same for every record
CURRENT_DATE as DATE_OF_REPORT
from SalesNumbers
where date_of_report >= current_date
group by Employee;
This runs in a script nightly and returns records like this:
Employee | shirts_DAILY | shirts_QUOTA | Shoes_DAILY | Shoes_QUOTA | DATE_OF_REPORT
--------------------------------------------------------------------------------------------------------
123 15 75 14 85 2019-08-30
That's the record from last Friday Night's report. I'm trying to figure out a way to add a column for each category that would take the sum of daily totals (shirts_DAILY, shoes_DAILY) for each category on preceding weekdays (running sunday through saturday as a week) and divide by that category's quota (shirts_QUOTA, shoes_QUOTA).
For example, here are records from sunday through thursday
Employee | shirts_DAILY | shirts_QUOTA | Shoes_DAILY | Shoes_QUOTA | DATE_OF_REPORT
--------------------------------------------------------------------------------------------------------
123 15 75 16 85 2019-08-25
123 4 75 2 85 2019-08-26
123 8 75 6 85 2019-08-27
123 2 75 8 85 2019-08-28
123 15 75 14 85 2019-08-29
With my new change, I would want Friday night's record to take the sum of sunday through thursday's daily records and divide by the quota (including friday's daily in the sum)
Friday night's record with new column:
Employee | shirts_DAILY | shirts_QUOTA | shirtsPercent | Shoes_DAILY | Shoes_QUOTA | shoesPercent | DATE_OF_REPORT
-----------------------------------------------------------------------------------------------------------------------------------------------
123 2 75 61.3 7 85 62.4 2019-08-30
So friday's run added 15,4,8,2,15,2 for the shirts for 46/75 and 7,14,8,6,2,16 for shoes for 53/85. So the daily sum of each for the preceding week, including present day daily totals, if that makes sense.
What is the best way for me to achieve this?
SELECT Employee,
sum(case when category = 'Shirts' and date_of_report >= current date then
daily_total else 0 end) as Shirts_DAILY,
sum(case when category = 'Shirts' and date_of_report >= current date then
weekly_quota else 0 end) as Shirts_QUOTA,
( sum(case when category = 'Shirts' then
daily_total else 0 end) * 100 ) /
( sum(case when category = 'Shirts' and date_of_report >= current date then
weekly_quota else 0 end) ) as Shirts_PERCENT,
CURRENT_DATE as DATE_OF_REPORT
from SalesNumbers
where date_of_report >= ( current date - ( dayofweek(current date) - 1 ) days )
group by Employee

Get collection of integers from counter

Which would be the best way to get the number of people hired on each day of the week for 7 years from a table People that has their entry_date with a day-month-year as 01-Jun-91.
For example:
2000 2001 2002 etc..
SUN 2 0 1
MON 0 0 2
Do I have to create a counter for each day of each year? Like Sun2000, Sun2001 etc?
You need to join each day of the week with your entry_date and pivot the results.
SQL Fiddle
Query:
with x(days) as (
select 'sunday' from dual union all
select 'monday' from dual union all
select 'tuesday' from dual union all
select 'wednesday' from dual union all
select 'thursday' from dual union all
select 'friday' from dual union all
select 'saturday' from dual
)
select * from (
select x.days,
extract(year from emp.entry_date) entry_year
from x left outer join emp
on x.days = to_char(emp.entry_date,'fmday')
)
pivot(count(entry_year)
for entry_year in (
2007,
2008,
2009,
2010,
2011,
2012
)
)
order by
case days when 'sunday' then 1
when'monday' then 2
when'tuesday' then 3
when'wednesday' then 4
when'thursday' then 5
when'friday' then 6
when'saturday' then 7
end
Results:
| DAYS | 2007 | 2008 | 2009 | 2010 | 2011 | 2012 |
|-----------|------|------|------|------|------|------|
| sunday | 0 | 0 | 0 | 0 | 0 | 0 |
| monday | 0 | 0 | 0 | 2 | 0 | 0 |
| tuesday | 0 | 0 | 0 | 0 | 1 | 0 |
| wednesday | 0 | 0 | 0 | 1 | 2 | 1 |
| thursday | 0 | 0 | 0 | 0 | 0 | 3 |
| friday | 0 | 0 | 0 | 0 | 0 | 0 |
| saturday | 0 | 0 | 0 | 0 | 0 | 0 |
You need to use group by on the year and entry_date to get the count of employees joined for each date.
For example:
Rem -- Assuming following table structure
create table People(id number, name varchar2(20), entry_date date);
Rem -- Following groups the results
select extract(year from entry_date) "Year", entry_date, count(id)
from People
where extract(year from entry_date) between 2008 and 2015
group by extract(year from entry_date), entry_date
order by extract(year from entry_date), entry_date;
Check this sqlfiddle to explore more.
Depending on the version of Oracle you're using (10g doesn't have the PIVOT function, for example), you might try something like the following conditional aggregation:
SELECT day_abbrev
, SUM(CASE WHEN year_num = 2000 THEN person_cnt ELSE 0 END) AS "2000"
, SUM(CASE WHEN year_num = 2001 THEN person_cnt ELSE 0 END) AS "2001"
, SUM(CASE WHEN year_num = 2002 THEN person_cnt ELSE 0 END) AS "2002"
, SUM(CASE WHEN year_num = 2003 THEN person_cnt ELSE 0 END) AS "2003"
, SUM(CASE WHEN year_num = 2004 THEN person_cnt ELSE 0 END) AS "2004"
, SUM(CASE WHEN year_num = 2005 THEN person_cnt ELSE 0 END) AS "2005"
, SUM(CASE WHEN year_num = 2006 THEN person_cnt ELSE 0 END) AS "2006"
FROM (
SELECT TO_CHAR(entry_date, 'DY') AS day_abbrev
, EXTRACT(YEAR FROM entry_date) AS year_num
, COUNT(*) AS person_cnt
FROM people
GROUP BY TO_CHAR(entry_date, 'DY'), EXTRACT(YEAR FROM entry_date)
) GROUP BY day_abbrev
ORDER BY TO_CHAR(NEXT_DAY(SYSDATE, day_abbrev), 'D');

Query for Dedit/Credit Transactions

Here is Query I am using :
select Date2,
sum(case when Type='Debit' then Amount else 0 end)as DebitAmount,
sum(case when Type='Credit' then Amount else 0 end)as CreditAmount,
((sum(case when Type='Debit' then Amount else 0 end))-sum(case when Type='Credit' then Amount else 0 end)) as Balance
from MainTransaction
group by MainTransaction.Date2
order by Date2
OutPut :
Date | Debit | Credit | Balance
-----------+---------+--------+-----------
2015-02-10 | 0.0 | 0 | 0.0
2015-02-12 | 19200.0 | 0 | 19200.0
2015-03-01 | 62000.0 | 0 | 62000.0
2015-03-08 | 999.0 | 0 | 999.0
2015-03-09 | 10064.0 | 0 | 10064.0
What I want it to display total balance as well , I mean like date is 11.03.2015 it will also display total debit till date 11.03.2015 -credit till date 11.03.2015..
What should I do .. I simply can't do sum as I am using group by date2..
Set {0} = '2015-03-11'
select ifnull(mt.Date2, mt.Date2s),
sum(case when mt.Type='Debit' then mt.Amount else 0 end)as DebitAmount,
sum(case when mt.Type='Credit' then mt.Amount else 0 end)as CreditAmount,
((sum(case when mt.Type='Debit' then mt.Amount else 0 end))-sum(case when mt.Type ='Credit' then mt.Amount else 0 end)) as Balance
from (
select mt.*, sd.*
from MainTransaction as mt
left join
(select {0} as Date2s) as sd On mt.date2 = sd.Date2s
where mt.date2 < {0}
union all
select mt.*, sd.*
from (select {0} as Date2s) as sd
left join
MainTransaction as mt On mt.date2 = sd.Date2s
where mt.date2 is null
) as mt
group by ifnull(mt.Date2, mt.Date2s)
order by ifnull(mt.Date2, mt.Date2s)

How to count sql from one column, and display it in two column

I have a table like this:
idrecord | date
----------------------------------------------
INC-20140308102029 | 2014-03-08 00:00:00.000
INC-20140308102840 | 2014-03-06 00:00:00.000
INC-20140310164404 | 2014-03-10 00:00:00.000
INC-20140311075714 | 2014-03-09 00:00:00.000
NRM-20140310130512 | 2014-04-02 00:00:00.000
NRM-20140311134720 | 2014-03-11 00:00:00.000
USF-20140317212232 | 2014-03-17 00:00:00.000
USF-20140321075402 | 2014-03-18 00:00:00.000
USF-20140321083137 | 2014-03-21 00:00:00.000
how to count this table and display result like this:
month | INC | NRM | USF
march | 4 | 1 | 3
April | 0 | 1 | 0
Thank you
You'd use case to count 1 or zero depending on the string matching or not. Use sum to count.
select
extract(month from thedate) as whichmonth,
sum( case when idrecord like 'INC%' then 1 else 0 end) as inc,
sum( case when idrecord like 'NRM%' then 1 else 0 end) as nrm,
sum( case when idrecord like 'USF%' then 1 else 0 end) as usf
from mytable
group by extract(month from thedate);
The function to extract the month from the date may vary from dbms to dbms. Look the appropriate function up in Google, if extract doesn't work for you.
Don't use the name date for a column. Date is a reserved word in SQL.
Try this
SELECT convert(char(3), date, 0) AS Month,
SUM(Case when LEFT(idrecord,3) = 'INC' then 1 else 0 end) as 'INC',
SUM(Case when LEFT(idrecord,3) = 'NRM' then 1 else 0 end) as 'NRM',
SUM(Case when LEFT(idrecord,3) = 'USF' then 1 else 0 end) as 'USF'
FROM Table1
Group By convert(char(3), date, 0)
Fiddle Demo
or:
SELECT datename(mm, date) AS Month,
SUM(Case when LEFT(idrecord,3) = 'INC' then 1 else 0 end) as 'INC',
SUM(Case when LEFT(idrecord,3) = 'NRM' then 1 else 0 end) as 'NRM',
SUM(Case when LEFT(idrecord,3) = 'USF' then 1 else 0 end) as 'USF'
FROM Table1
Group By datename(mm, date)
Fiddle Demo
Output:
month | INC | NRM | USF
march | 4 | 1 | 3
April | 0 | 1 | 0
try this one
select month (date) as month,
count( case when idrecord like 'INC%' then 1 else 0 end) as inc,
count( case when idrecord like 'NRM%' then 1 else 0 end) as nrm,
count( case when idrecord like 'USF%' then 1 else 0 end) as usf
from table
group by month;

SQL query to calculate total per month as a column

I am stuck on a SQL query. I am using PostgreSQL. I need to get the total for each month for all states.
table A
--------------------------------------------------------
created | Name | Agent_id | Total
--------------------------------------------------------
3/14/2013 | Harun | 1A | 5
3/14/2013 | Hardi | 2A | 20
4/14/2013 | Nizar | 3A | 30
5/14/2013 | moyes | 4A | 20
table B
----------------------------
Agent_id| state_id
----------------------------
1A | 1
2A | 1
3A | 1
4A | 2
table C
----------------------------
state_id | State
----------------------------
1 | Jakarta
2 | Singapore
3 | Kuala lumpur
DESIRED RESULT:
-----------------------------------------------------------------------------------------------
No |State | Januari | February | March | April | Mei ... December| Total
-----------------------------------------------------------------------------------------------
1 |Jakarta |0 |0 |25 | 30 | 0 ... | 55
2 |Singapore |0 |0 | 0 | 0 | 20 ... | 20
3 |Kuala Lumpur |0 |0 | 0 | 0 | 0 ... | 0
to have all state with no data in table A / B you have to use OUTER JOIN
to complete #bma answer
select
no,
state,
sum(case when month = 1 then total else 0 end) as januari,
sum(case when month = 2 then total else 0 end) as februari,
sum(case when month = 3 then total else 0 end) as mars,
sum(case when month = 4 then total else 0 end) as april,
sum(case when month = 5 then total else 0 end) as may,
sum(case when month = 6 then total else 0 end) as juni,
sum(case when month = 7 then total else 0 end) as juli,
sum(case when month = 8 then total else 0 end) as august,
sum(case when month = 9 then total else 0 end) as september,
sum(case when month = 10 then total else 0 end) as october,
sum(case when month = 11 then total else 0 end) as november,
sum(case when month = 12 then total else 0 end) as december,
sum(coalesce(total,0)) as total
from (
select
c.state_id as no,
extract(month from created) as month,
state,
sum(total) as total
from tablec c
left join tableb b on ( b.state_id = c.state_id)
left join tablea a on ( a.agent_id = b.agent_id)
group by c.state_id,state,month
) sales
group by no,state;
SQL Fiddle demo
Actually i do not know much about postgres sql this is a try see if this works
try this
Select EXTRACT(MONTH FROM TIMESTAMP table A.created) ,
table C.State , SUM(Total) From table A , table B , table C
Where table A.Agent_id = table B.Agent_id
And table B.state_id = table C.state_id
Group by table C.State , EXTRACT(MONTH FROM TIMESTAMP table A.created);
Something like the following should give you results like your sample results. I'm not sure what the "No" column was though. This query is untested.
select state,
sum(case when mm = 1 then total else 0 end) as jan,
sum(case when mm = 2 then total else 0 end) as feb,
sum(case when mm = 3 then total else 0 end) as mar,
sum(case when mm = 4 then total else 0 end) as apr,
sum(case when mm = 5 then total else 0 end) as may,
sum(case when mm = 6 then total else 0 end) as jun,
sum(case when mm = 7 then total else 0 end) as jul,
sum(case when mm = 8 then total else 0 end) as aug,
sum(case when mm = 9 then total else 0 end) as sep,
sum(case when mm = 10 then total else 0 end) as oct,
sum(case when mm = 11 then total else 0 end) as nov,
sum(case when mm = 12 then total else 0 end) as dec,
sum(total) as total
from (
select extract(month from created) as mm,
state,
sum(total) as total
from table_a
group by state,mm
) s
group by state;