Getting calculated percentages within group using SQL - sql

I have a dataset:
Date
June 2011
July 2011
Aug 2011
Sep 2011
Oct 2011
Jan 2012
Feb 2012
Mar 2012
Apr 2013
May 2013
that records down the date registered for each yearly project. (There are no project IDs however)
I would like to add in the additional variable Percentage, which represent the average progress made for that month. (For instance, if the project is registered for 4 months, then each month would progress incrementally by 25 %, (25,50,75,100)), specifically:
Percentage Date
20 June 2011
40 July 2011
60 Aug 2011
80 Sep 2011
100 Oct 2011
33 Jan 2012
66 Feb 2012
100 Mar 2012
50 Apr 2013
100 May 2013
However, my main problem would be that I am unable to know the starting month (period) and ending month (period) for each project for each year.
Are there any functions in SQL to create the calculated percentages in this case? I thought of creating a year variable and further using an indicator to indicate the start/end of the progress, but could not move on further.
Thank you again!

You can try this query.
Getting ROW_NUMBER() by year(dates) on subquery.
then get the percent.
SELECT (FLOOR(CAST(T2.RK AS decimal) * 100/(
SELECT COUNT(1) AS Totle
FROM T
WHERE year(dates) = T2.dates))) [Percentage],
T2.dates as [years],
T2.months as [months]
FROM
(
SELECT ROW_NUMBER() OVER(PARTITION BY year(dates) ORDER BY dates DESC) AS RK,
year(dates) as dates,
month(dates) as months
FROM T
) AS T2
GROUP BY T2.dates,T2.RK,T2.months

Here is a simple Pseudo sql to get what you want . ?
select Year(date), Month(date) ,
(select sum(Progress_percentage) from dataset b where b.date <=a.date ) as
subquery_percentage
from dataset a
group by Year(date), Month(date)

Related

SUM and Count in one SQL Query

I have this kind of data
time Members
-------------------------------------------------- -----------
Jun 23 2016 1
Jun 23 2016 1
Jun 23 2016 2
Jun 29 2016 6
Jul 11 2016 3
Jul 11 2016 1
Jul 13 2016 1
I obtained this data using this sql query
SELECT CONVERT (VARCHAR(12), a.registered_time), COUNT(b.member_id) AS Members
FROM b
Inner JOIN a ON b.mirror_id = a.mirror_id
GROUP BY
(a.registered_time) order by a.registered_time
I want to get the sum of total numbers if they are of the same date for exampple the date of June 23 2016 will have total members of 4 and so on. Is it possible to have SUM() FUnction on Count()? How can I do this?
Convert the value to a date and include that in both the select and group by:
SELECT CONVERT(date, a.registered_time) as dte, COUNT(b.member_id) AS Members
FROM b JOIN
a
ON b.mirror_id = a.mirror_id
GROUP BY CONVERT(date, a.registered_time)
ORDER BY CONVERT(date, a.registered_time);

SQL Difference Between Sum of Two Months

I'm trying to find the difference between the previous years month and current years month. An example would be the SUM of sales for January 2013 and the difference of SUM of sales for January 2014 sales. This is being done to see how much we made from the previous year. I have a group by that shows the total sales by month and year. I'm having trouble on defining how to find the difference between the two months. Thank you for your help. Its greatly appreciated.
Table
Date Sales
1/1/2013 100
1/12/2013 150
1/21/2013 90
1/4/2014 200
1/17/2014 50
1/20/2014 100
Result of Group By
Jan 2013
340
Jan 2014
350
Difference
Jan 2014 - Jan 2013
340 - 350 = 10
The best way to do this depends on the database. The first thing you need to do is to aggregate the data. Then a simple join will get the data you need. Here is one method:
with ym as (
select year(date) as yr, month(date) as mon,
sum(sales) as sales
from table t
group by year(date), month(date)
)
select ym.yr, ym.mon, ym.sales, ymprev.sales as prev_sales,
(ym.sales - ymprev.sales) as diff
from ym join
ym ymprev
on ymprev.yr = ym.yr - 1 and ymprev.mon = ym.mon;

oracle pivot query suggestion

I have a simple table that has data like the following
FiscalYear Month Value
2013 01 10
2013 02 15
....
2014 01 15
2014 02 20
using Oracle(11g) Pivot query is it possible to get something like this?
Month 2013 2014
01 10 15
02 15 20
SELECT month, value_2013, value_2014
FROM (SELECT fiscalyear, month, value FROM your_table)
PIVOT (SUM (value) AS value
FOR (fiscal_year)
IN ('2013', '2014'))

Can I get a whole year one table or do I have to change the query for each month?

The following code is probably self explanatory
Lists number of active subscribers 1st of june
select
count(subscribers) as activeSubscribers
from subscriberlist sub
where
to_date('2012-06', 'yyyy-mm')
between sub.firstDayOfSubscription and sub.lastDayOfSubscription
But if I want to get the number of subscribers in the beginning of every month the past year, what could I do (besides changing the date in the query and repeating).
You can generate a list of months as follows:
SELECT add_months (trunc (to_date('01/01/2012','MM/DD/YYYY'), 'MM'), 1*LEVEL -1) FirstDay
FROM Dual
CONNECT BY LEVEL <= MONTHS_BETWEEN(to_date('12/31/2012','MM/DD/YYYY'), to_date('01/01/2012','MM/DD/YYYY')) + 1
ORDER BY FirstDay
This would give you the following output:
FIRSTDAY
--------
January, 01 2012 00:00:00+0000
February, 01 2012 00:00:00+0000
March, 01 2012 00:00:00+0000
April, 01 2012 00:00:00+0000
May, 01 2012 00:00:00+0000
June, 01 2012 00:00:00+0000
July, 01 2012 00:00:00+0000
August, 01 2012 00:00:00+0000
September, 01 2012 00:00:00+0000
October, 01 2012 00:00:00+0000
November, 01 2012 00:00:00+0000
December, 01 2012 00:00:00+0000
You can then include that query as an inline view as follows:
SELECT months.FirstDay,
(SELECT count(subscribers)
FROM subscriberlist sub
WHERE months.FirstDay BETWEEN sub.firstDayOfSubscription AND sub.lastDayOfSubscription
) AS activeSubscribers
FROM (SELECT add_months(trunc (to_date('01/01/2012','MM/DD/YYYY'), 'MM'), 1*LEVEL -1) FirstDay
FROM Dual
CONNECT BY LEVEL <= MONTHS_BETWEEN(to_date('12/31/2012','MM/DD/YYYY'), to_date('01/01/2012','MM/DD/YYYY')) + 1
ORDER BY FirstDay) Months
I'd probably wrap this in a sproc that accepts #startDate and #endDate parameters to define the date range you're interested, but I followed your syntax with the date range being defined with strings.
I was playing with this using this SqlFiddle
This might be a good use for a date lookup table. I've found them useful enough to try to always have one in any decent-sized database.
Build a table in your database with one line per day, for a reasonable period of time... say from ten years ago to ten years from now (depending on what sort of queries you run).
In the table add a number of fields based on the date:
Date
Week
Week_Ending
Month
Month_DayOf
Month_Beginning
Year
Business_Day
Weekend
Holiday
etc...
The handy thing about this is that once it's populated, you can join it to other tables by the date field to summarize or filter data by date however you need. For example:
select
dt.Month
count(subscribers) as activeSubscribers
from subscriberlist sub
join (select unique datelookup.Month_Beginning
from date_reference ) dt
on dt.Month_Beginning between sub.firstDayOfSubscription and sub.lastDayOfSubscription
group by
dt.Month;
(Off the top of my head, I'm not sure if this syntax is exactly right, especially for Oracle.)
If you don't have the ability to add one to your database, you can create a temporary table as part of your query and fill it with the date ranges you're concerned with.

How to inserting an intermediate row?

I have the following table:
Year Line January Febraury March .... December
2011 B1 5 10 20
2012 B1 10 15 25 ...
2011 A1 4 8 10 ...
And I want to insert a subtotal row each two lines (if exists), in particular each time year and Line changing: so
Year Line January Febraury March .... December
2011 B1 5 10 20
2012 B1 10 15 25 ...
--- B1 +100% +50% +25% ..
2011 A1 4 8 10 ...
How can I do this in T-SQL ?
Maybe using cursor ?
Are you certain that you want to insert a new row? Or just be able to calculate that subtotal when you query the data?
Query Version
SELECT
Year,
Line,
SUM(January) AS January,
SUM(February) AS February,
...
SUM(December) AS December
FROM
yourTable
GROUP BY
Year,
Line
WITH
ROLLUP
ORDER BY
Year,
Line
Insert Version
If you just one one level of summary, remove the WITH ROLLUP
INSERT INTO
yourTable
SELECT
Year,
NULL,
SUM(January) AS January,
SUM(February) AS February,
...
SUM(December) AS December
FROM
yourTable
GROUP BY
Year
WITH
ROLLUP
EDIT Follow question edit
I strongly suggest that you mean a query, not a change to the actual data. I also suggest that you either build these lines in your reporting environment, or you put the % values to the right of each record...
SELECT
this_year.Year,
this_year.Line,
this_year.January,
CAST(this_year.January AS DECIMAL(8,2)) / CAST(last_year.January AS DECIMAL(8,2)) AS January_Change,
...
FROM
yourTable AS this_year
LEFT JOIN
yourTable AS last_year
ON last_year.year = this_year.year-1
AND last_year.line = this_year.line