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

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;

Related

Looping Through Dates in SQL? (Databricks)

I am currently learning SQL and ran into a problem. Through my searches I have found that looping in SQL is a big no-no, so I was wondering if anyone could point me into the correct direction?
The dataframe looks like this:
Group
ATP Date
JTH Date
A
5/17/2022
6/17/2022
A
5/17/2022
Null
B
5/17/2022
Null
A
5/16/2022
6/16/2022
B
5/16/2022
6/16/2022
B
5/15/2022
6/17/2022
B
5/15/2022
Null
A
5/14/2022
6/1/2022
A
5/13/2022
Null
A
5/13/2022
6/1/2022
A
5/13/2022
6/5/2022
I am trying to make a query to pull this:
Date
Group
CountNo
CountYes
Ratio (No/Yes)
5/17/2022
A
1
1
1
5/17/2022
B
0
1
0
5/16/2022
A
1
0
Null
5/16/2022
B
2
1
2
5/14/2022
A
1
0
Null
5/13/2022
A
2
0
Null
This is what I currently created:
max(ATP_Date) as Date,
Group,
sum(
case
when ATP_Date < '2022-05-18'
and JTH_Date > '2022-05-18' then 1
else 0
END
) as CountNo,
sum(
case
when ATP_Date < '2022-05-18'
and JTH_Date IS null then 1
else 0
END
) as CountYes,
sum(
case
when ATP_date < '2022-05-18'
and JTH_Date > '2022-05-18' then 1
else 0
END
) / sum(
case
when ATP_Date < '2022-05-18'
and JTH_Date IS null then 1
else 0
END
) as ratio
from
dataframe
where group = "A"
GROUP BY group
Which outputs this:
Date
Group
CountNo
CountYes
Ratio
5/17/2022
A
318
1064
0.3
This is what I want, but I need to do it for each date for ~ last 4 years, so it looks like the second table posted. I could manually edit the dates for each query, but that would take forever. This made me think of looping. I believe I would basically need to loop through the Select portion with dates, in order to get the output I want. If anyone has advice or could point in me in the correction direction, it would be greatly appreciated, thanks.
I couldn't write the query as a comment, so posting it here. If it's not what you are expecting, let me know will delete this.
Assuming 2022-05-18 is constant (as per your sample)
Creating sample table
create or replace table dt_query
(group string, atp_date date, jth_date date);
insert into dt_query values
('A','2022-05-17','2022-06-17')
,('A','2022-05-17',NULL)
,('B','2022-05-17',NULL)
,('A','2022-05-16','2022-06-16')
,('B','2022-05-16','2022-06-16')
,('B','2022-05-16','2022-06-15')
,('B','2022-05-16',NULL)
Slightly modified your select statement
select
max(ATP_Date) as Date,
Group,
sum(
case
when ATP_Date < '2022-05-18'
and JTH_Date > '2022-05-18' then 1
else 0
END
) as CountNo,
sum(
case
when ATP_Date < '2022-05-18'
and JTH_Date IS null then 1
else 0
END
) as CountYes,
sum(
case
when ATP_date < '2022-05-18'
and JTH_Date > '2022-05-18' then 1
else 0
END
) / sum(
case
when ATP_Date < '2022-05-18'
and JTH_Date IS null then 1
else 0
END
) as ratio
from
dt_query
GROUP BY group,atp_date
The result matches with what you are expecting.
To avoid using loops here you can include atp_date into the group by clause which will result in 1 row for each combination of that date plus the "grouping" column
It isn't clear why you compare to '2022-05-18' but this appears to be the day following the maximum date found in atp_date. So to avoid hardcoding, you could approach it by using a derived table of 1 row, cross joined to the data:
SELECT
ATP_Date
, grouping
, sum(CASE
WHEN ATP_Date < cj.max_dt AND JTH_Date > cj.max_dt
THEN 1
ELSE 0
END) AS CountNo
, sum(CASE
WHEN ATP_Date < cj.max_dt AND JTH_Date IS NULL
THEN 1
ELSE 0
END) AS CountYes
, sum(CASE
WHEN ATP_date < cj.max_dt AND JTH_Date > cj.max_dt
THEN 1
ELSE 0
END)
/ sum(CASE
WHEN ATP_Date < cj.max_dt AND JTH_Date IS NULL
THEN 1
ELSE NULL
END) AS ratio
FROM dt_query
CROSS JOIN (select max(atp_date) + interval '1 day' max_dt from dt_query) AS cj
GROUP BY
grouping
, atp_date
ORDER BY
atp_date DESC
, grouping
atp_date | grouping | countno | countyes | ratio
:--------- | :------- | ------: | -------: | ----:
2022-05-17 | A | 1 | 1 | 1
2022-05-17 | B | 0 | 1 | 0
2022-05-16 | A | 1 | 0 | null
2022-05-16 | B | 2 | 1 | 2
2022-05-14 | A | 1 | 0 | null
2022-05-13 | A | 2 | 1 | 2
db<>fiddle here
nb: to avoid issues with the term "group" I have used the column name "grouping" instead, and the example sql is written in postgres so there may be some syntax that needs alteration (e.g. the addition of 1 day). Also note that the ratio calcuation can result in a divide by zero error so instead of zero I used NULL.

Average call volumes between times , total for months

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

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)

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;