How to inserting an intermediate row? - sql

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

Related

Count total without duplicate records

I have a table that contains the following columns: TrackingStatus, Year, Month, Order, Notes
I need to calculate the total number of tracking status for each year and month.
For example, if the table contains the following orders:
TrackingStatus
Year
Month
Order
Notes
F
2020
1
33
F
2020
1
33
DFF
E
2020
2
36
xxx
A
2021
3
34
X1
A
2021
3
34
DD
A
2021
3
88
A
2021
2
45
The result should be:
• Tracking F , year 2020, month 1 the total will be one (because it's the same year, month, and order).
• Tracking A , year 2021, month 2 the total will be one. (because there is only one record with the same year, month, and order).
• Tracking A , year 2021, month 3 the total will be two. (because there are two orders within the same year and month).
So the expected SELECT output will be like that:
TrackingStatus
Year
Month
Total
F
2020
1
1
E
2020
2
1
A
2021
2
1
A
2021
3
2
I was trying to use group by but then it will count the number of records which in my scenario is wrong.
How can I get the total orders for each month without counting “duplicate” records?
Thank you
You can use a COUNT DISTINCT aggregation function, whereas the COUNT allows you to count the values, but the DISTINCT condition will allow each value only once.
SELECT TrackingStatus,
Year,
Month,
COUNT(DISTINCT Order) AS Total
FROM tab
GROUP BY TrackingStatus,
Year,
Month
ORDER BY Year,
Month
Here you can find a tested solution in a MySQL environment, though this should work with many DBMS.

Percent of change by year and month

I have code that distinctly counts authorizations grouped by month and year.
I added a calculated field to show the percent of change but my issue is I only want to get this percentage between the years by month.
My code calculates the percent for each previous row. which when pulled into SSRS displays the incorrect value after the for column.
Select D.Month
,D.Year
,count( distinct D.authorization_number) [Admission Events]
,CAST(lag(Count(distinct D.authorization_number), 1) over (order by D.month) - Count(distinct D.authorization_number) as FLOAT) / CAST(Count(distinct D.authorization_number)as FLOAT) [Admission Events Pct]
From #Detail D
Group BY D.Month
,D.Year
In these results I would like to only display the pct for year 2018 in SSRS.
Month Year Admission Events Admission Events Pct
1 2017 5919 NULL
1 2018 6057 -0.0227835562159485
2 2017 5302 0.142399094681252
2 2018 5234 0.0129919755445166
3 2017 5548 -0.0565969718817592
3 2018 5389 0.0295045462980145
4 2017 5128 0.0508970358814353
4 2018 5503 -0.0681446483736144
5 2017 5768 -0.0459431345353675
5 2018 5708 0.0105115627189909
6 2017 5461 0.0452298113898553
6 2018 2606 1.09554873369148
Is this what you want?
select t.*
from (<your query here>) t
where year = 2018;
You need a subquery or CTE so the where doesn't interfere with the lag().

Getting calculated percentages within group using 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)

sql query (Show unique rows in column)

I have following type of data in my Sql server:-
Field Value Month
Administrative 5 November
Counteracting 7 November
District1 9 November
District2 6 November
Administrative 1 December
Counteracting 2 December
District1 3 December
District2 4 December
Administrative 9 January
Counteracting 8 January
District1 5 January
District2 6 January
Now the problem is I am not able to figure out that how to show this data in the following format:-
Field November December January
Administrative 5 1 9
Counteracting 7 2 8
District1 9 3 5
District2 6 4 6
What you are trying to do is PIVOT the data. There are a few ways to perform this. If you know the values ahead of time, then you can hard-code the values.
You can use an aggregate function with a CASE statement:
select field,
sum(case when month ='November' then value end) November,
sum(case when month ='December' then value end) December,
sum(case when month ='January' then value end) January,
etc
from yourtable
group by field
See SQL Fiddle with Demo
In SQL Server 2005+ you can use the PIVOT function:
select field, November, December, January
from
(
select field,
value, month
from yourtable
) src
pivot
(
sum(value)
for month in (November, December, January, etc)
) piv
See SQL Fiddle with Demo
If you had an unknown number of values to transform into columns then you could use dynamic sql to pivot the data.
That is a typical pivoting problem. Check out the SQL Server PIVOT statement: http://msdn.microsoft.com/en-us/library/ms177410(v=sql.105).aspx
It will solve your problem.
You need to use Pivot, check out example:
http://blogs.msdn.com/b/spike/archive/2009/03/03/pivot-tables-in-sql-server-a-simple-sample.aspx

Generate year to date by month report in SQL [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Running total by grouped records in table
I am trying to put together an SQL statement that returns the SUM of a value by month, but on a year to date basis. In other words, for the month of March, I am looking to get the sum of a value for the months of January, February, and March.
I can easily do a group by to get a total for each month by itself, and potentially calculate the year to date value I need in my application from this data by looping through the results set. However, I was hoping to have some of this work handled with my SQL statement.
Has anyone ever tackled this type of problem with an SQL statement, and if so, what is the trick that I am missing?
My current sql statement for monthly data is similar to the following:
Select month, year, sum(value) from mytable group by month, year
If I include a where clause on the month, and only group by the year, I can get the result for a single month that I am looking for:
select year, sum(value) from mytable where month <= selectedMonth group by year
However, this requires me to have a particular month pre-selected or to utilize 12 different SQL statements to generate one clean result set.
Any guidance that can be provided would be greatly appreciated!
Update: The data is stored on an IBM iSeries.
declare #Q as table
(
mmonth INT,
value int
)
insert into #Q
values
(1,10),
(1,12),
(2,45),
(3,23)
select sum(January) as UpToJanuary,
sum(February)as UpToFebruary,
sum(March) as UpToMarch from (
select
case when mmonth<=1 then sum(value) end as [January] ,
case when mmonth<=2 then sum(value) end as [February],
case when mmonth<=3 then sum(value) end as [March]
from #Q
group by mmonth
) t
Produces:
UpToJanuary UpToFebruary UpToMarch
22 67 90
You get the idea, right?
NOTE: This could be done easier with PIVOT tables but I don't know if you are using SQL Server or not.
As far as I know DB2 does support windowing functions although I don't know if this is also supported on the iSeries version.
If windowing functions are supported (I believe IBM calls them OLAP functions) then the following should return what you want (provided I understood your question correctly)
select month,
year,
value,
sum(value) over (partition by year order by month asc) as sum_to_date
from mytable
order by year, month
create table mon
(
[y] int not null,
[m] int not null,
[value] int not null,
primary key (y,m))
select a.y, a.m, a.value, sum(b.value)
from mon a, mon b
where a.y = b.y and a.m >= b.m
group by a.y, a.m, a.value
2011 1 120 120
2011 2 130 250
2011 3 500 750
2011 4 10 760
2011 5 140 900
2011 6 100 1000
2011 7 110 1110
2011 8 90 1200
2011 9 70 1270
2011 10 150 1420
2011 11 170 1590
2011 12 600 2190
You should try to join the table to itself by month-behind-a-month condition and generate a synthetic month-group code to group by as follows:
select
sum(value),
year,
up_to_month
from (
select a.value,
a.year,
b.month as up_to_month
from table as a join table as b on a.year = b.year and b.month => a.month
)
group by up_to_month, year
gives that:
db2 => select * from my.rep
VALUE YEAR MONTH
----------- ----------- -----------
100 2011 1
200 2011 2
300 2011 3
400 2011 4
db2 -t -f rep.sql
1 YEAR UP_TO_MONTH
----------- ----------- -----------
100 2011 1
300 2011 2
600 2011 3
1000 2011 4