aggregate a few rows and display in oracle - sql

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

Related

Sales for each completed month in current year and previous year

For each of the 12 months, I'm looking to create a field that sums the sales dollars at the account level for the most recent month and the 2nd most recent month based on the current date.
For example, given that today's date is 2022-10-28, 'MostRecentNovember' would sum up sales from November 2021. '2ndMostRecentNovember' would sum up sales from November 2020. Once the current date moves into November 2022, this query would adjust to pull MostRecentNovember sales from 2022 and 2ndMostRecentNovember sales from 2021.
Conversely, given that today's date is 2022-10-28 'MostRecentJune' would sum up sales from June 2022 and '2ndMostRecentJune' would sum up sales from June 2021.
In the end state, each account would have 24 fields: January - December for Most Recent and January - December for 2nd most recent
Below is my attempt at this code, this gets partially there, but it's not getting what I need. I've also tried with a CTE, but that didn't seem to do it either
SELECT NovemberMostRecent_Value =
sum(case when datepart(year,tran_date) = datepart(year, getdate())
AND DATEPART(month, tran_date) = 11 then value else 0 end)
NovemberSecondMostRecent_Value =
sum(case when datepart(year,tran_date) = datepart(year, getdate())-1
AND DATEPART(month, tran_date) = 11 then value else 0 end)
Here's a snippet of the source data table
account_no
tran_date
value
123
2021-11-22
500
123
2021-11-01
500
123
2020-11-20
1500
123
2022-06-03
5000
123
2021-06-04
2000
456
2020-11-03
525
456
2021-11-04
125
A table of desired Results
account_no
NovemberMostRecent
November2ndMostRecent
June MostRecent
June2ndMostRecent
123
1000
1500
5000
2000
456
125
525
0
0
We use dense_rank() by year desc (partitioned by month) and pivot.
select *
from
(
select account_no
,value
,concat(datename(month, tran_date), '_', dense_rank() over(partition by month(tran_date) order by year(tran_date) desc)) as month_rnk
from t
) t
pivot (sum(value) for month_rnk in(June_1, June_2, November_1, November_2)) p
account_no
June_1
June_2
November_1
November_2
123
5000
2000
1000
1500
456
null
null
125
525
Fiddle

find the employee count based on hire date In Oracle

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>

Exclude results for a given year

I need to exclude Jerry from 2019 (orderyear) and only show sales for him in 2018. What can I add to my code to remove Jerry's 2019 sales. I am using SSMS 2016.
select orderyear, case when code = '2099' then 'Laura'
when code = '3099' then 'John'
when code = '4099' then 'Jerry'
end as 'Members', count(sales)numberofsales
from mytable
group by orderyear, case when code = '2099' then 'Laura'
when code = '3099' then 'John'
when code = '4099' then 'Tony'
end
Results:
orderyear members numberofsales
2018 John 200
2019 John 100
2018 Laura 300
2019 Laura 350
2018 Jerry 400
2019 Jerry 450
Requested:
orderyear members numberofsales
2018 John 200
2019 John 100
2018 Laura 300
2019 Laura 350
2018 Jerry 400
Add:
where not (code = '4099' and orderyear = 2019)
You can simplify to this:
select
orderyear,
case code
when '2099' then 'Laura'
when '3099' then 'John'
when '4099' then 'Jerry'
end as Members,
count(sales) numberofsales
from mytable
where
orderyear <> 2019 or code <> '4099'
group by
orderyear,
code

T-SQL Running Monthly Totals Including Missing Months

I know this sounds really simple but I just cannot seem to get my head around it.
I have a temporary table that holds for example, Handler, MonthName, MonthNumber and MTD, which is a total for that month. What I need to do with that data is then create a running total for each Handler, from April to March. Now, here is the bit I am struggling with. Not all Handlers will have data for all months.
For example.
Handler MonthName MonthNo MTD
Julian Slaughter April 1 10000
Julian Slaughter June 3 12000
Julian Slaughter July 4 10000
Julian Slaughter September 6 12000
Bob Monkhouse April 1 5000
Bob Monkhouse July 4 5000
So I want the results to look like this
Julian Slaughter April 1 10000
Julian Slaughter May 2 10000
Julian Slaughter June 3 22000
Julian Slaughter July 4 32000
Julian Slaughter August 5 32000
Julian Slaughter September 6 44000
...and so on until March
Bob Monkhouse April 1 5000
Bob Monkhouse May 2 5000
Bob Monkhouse June 3 5000
Bob Monkhouse July 4 10000
...and so on until March
I have tried LEFT JOIN onto a table of the Month Names\Numbers and I have had an attempt at
OVER(PARTITION ..... ORDER BY ..... RANGE\ROWS)
but can't get the missing months.
Thanks in advance, sorry for the poor formatting, not sure how to do tables on here.
EDIT - Here is my LEFT JOIN attempt
SELECT
Months.MonthNo,
Department,
Executive,
#8.MonthNo,
MTD = SUM([TY MTD Prem]) OVER (PARTITION BY Department, Executive, [Exec Code] ORDER BY #8.MonthNo RANGE UNBOUNDED PRECEDING)
FROM Months
LEFT JOIN #8 ON Months.MonthNo = #8.MonthNo
For one Executive, I only get 4 rows, not the 12 I need. Can't show you the results for Data Protection purposes.
DECLARE #start_date date, #end_date date
SELECT #start_date='2012-04-01',#end_date='2013-03-31'
;WITH xo AS
(
SELECT #start_date AS cte_start_date
UNION ALL
SELECT DATEADD(MONTH, 1, cte_start_date)
FROM xo
WHERE DATEADD(MONTH, 1, cte_start_date) <= #end_date
), x as (
select *,row_number() over (order by cte_start_date) monthno
from xo
)
, y as (
select distinct handler from test
)
SELECT y.handler, datename(mm,x.cte_start_date), x.monthno
,(select sum(mtd) from test a where a.handler=y.handler and a.monthno<=x.monthno) mtd
FROM y
cross join x
order by 1,3
see example on SQLFiddle http://sqlfiddle.com/#!3/7d483/15
Sorry for the delay. The proposed solution worked a treat. I had to use the same code several times in various other parts of my giant query but it worked great.

GROUP BY expression (part of column) instead of whole column

I'm creating a query:
I need to get the quantity of returns made for each year.
ReturnDate is the specific date each member has, when the return was made.
To get the year I'm using LEFT(ReturnDate,4).
It all seem OK so far, but I need the list to show Year, City and the complete number of returns for that city, like:
YEAR CITY QUANTITY
2011 London 300
2011 Stockholm 40
2012 London 250
Now, I'm not getting:
YEAR CITY QUANTITY
2011 London 200
2011 London 100
2011 Stockholm 30
2011 Stockholm 10
2012 London 250
This is what I've come up with so far:
SELECT LEFT(ReturnDate,4) AS Year, City, COUNT(ReturnDate) AS Quantity
FROM Member
GROUP BY ReturnDate, City
Try:
GROUP BY LEFT(ReturnDate, 4), City
Alternatively, you can try using DATEPART:
SELECT DATEPART(yyyy, ReturnDate) AS Year, City, COUNT(ReturnDate) AS Quantity
FROM Member
GROUP BY DATEPART(yyyy, ReturnDate), City