SQL Count with rollup shows totals as NULL - sql

I need to know how I can replace the NULL with total.
Here is a copy of my query using ROLLUP.
SELECT DATEPART(YEAR, study_date) AS 'Year',
COUNT(distinct study_uid) AS 'Studies'
FROM local_studies
GROUP BY rollup (DATEPART(YEAR, study_date))
ORDER BY 'Year' DESC
This is the output:
Year Studies
2020 497
2019 165743
2018 165043
2017 182712
2016 210700
2015 219373
2014 214097
2013 211566
2012 212900
2011 217957
2010 213542
2009 193510
2008 95434
2007 53722
2006 44422
2005 12119
2004 129
2003 65
2000 4
NULL 2413535
I like to see the 'NULL" value replace with 'Total': (as shown below)
Year Studies
2020 497
2019 165743
2018 165043
2017 182712
2016 210700
2015 219373
2014 214097
2013 211566
2012 212900
2011 217957
2010 213542
2009 193510
2008 95434
2007 53722
2006 44422
2005 12119
2004 129
2003 65
2000 4
Total 2413535
Any advice for converting that NULL to the word TOTAL would be greatly appreciated.

I usually just use coalesce():
SELECT COALESCE(DATENAME(YEAR, study_date), 'Total') AS Year,
COUNT(distinct study_uid) AS 'Studies'
FROM local_studies
GROUP BY rollup (DATENAME(YEAR, study_date))
ORDER BY Year DESC;
Note that this switches to using DATENAME() so the column is a string and not a number.
Also, this doesn't work so well if the value could be NULL. For that, there is the GROUPING() function.

SELECT CASE GROUPING_ID(DATEPART(YEAR, study_date)) WHEN 1 THEN 'Total' ELSE CAST(DATEPART(YEAR, study_date) AS VARCHAR(10)) END AS 'Year',
COUNT(distinct study_uid) AS 'Studies'
FROM local_studies
GROUP BY rollup (DATEPART(YEAR, study_date))
ORDER BY GROUPING_ID(DATEPART(YEAR, study_date)), 'Year' DESC;

Related

How to drop a field from a running count

I am tasked with trying to come up with a total count for the number of clients we have had in any given year. I am able to run a total count of the clients we have had, but I want to drop them from the running total when they offboard from us (i.e. #EndDate)
DECLARE #EndDate Date
SET #EndDate = (SELECT DISTINCT LOAEndDate FROM tblCompany)
SELECT DISTINCT Year(DateBecameClient) AS [Year],
Count(CompanyId) OVER (ORDER BY Year(DateBecameClient)) AS NumberofClients
FROM [tblCompany] AS Company
ORDER BY [Year]
Here is the output that I get without including #EndDate.
--------------------
Year NumberofClients
2001 3
2002 6
2003 9
2004 10
2005 13
2006 15
2007 16
2008 26
2009 36
2010 78
2011 135
2012 204
2013 314
2014 385
2015 456
2016 471
2017 496
2018 507
2019 513
2020 514
2021 516
I presume that you have a separate date that indicates when the client left. You'll want to counterbalance with a -1 via a union. If a client was added and lost within the same year it'll never be counted:
with data as (
select year(DateBecameClient) as yr, 1 as num
from tblCompany
union all
select year(DateLostClient), -1
from tblCompany
)
select yr as "Year", sum(sum(num)) over (order by yr) as NumberOfClients
from data
group by yr
order by "Year";
I'm using grouping with a sum of sums to get around needing distinct. This is basically the same as your query except for the addition of the negative counters.

Query that returns maximum and corresponding FK(ID) group by year which comes from another select that has averages group by FK(ID) and year

I have a raw table which contains the id (pk AI), farm_fk (or HERD), birthdate, nm (some indicator).
I want to get the maximum of nm averages for each existing year and corresponding farm_fk.
What is DID?
1st from table I got the averages of nm for each farm_fk group by year which returns some thing like this I added the inner select query (here I added order by also to ease of reading)
SELECT
YEAR(FA_BDATE) AS BYEAR, FARM_FK AS HERD, AVG(NET_MERIT) AS NM
FROM
__FARM_ANALYTICS_TBL
GROUP BY
FARM_FK, YEAR(FA_BDATE)
ORDER BY
HERD, BYEAR
Output:
2006 10045 -181.553596496582
2007 10045 -252.123779296875
2008 10045 -97.3785720467567
2009 10045 -46.0490081493671
2010 10045 -2.05634630137476
2011 10045 33.5371181927621
2012 10045 74.3363304953117
2013 10045 124.057859333072
2014 10045 177.423686878542
2015 10045 188.846870697982
2016 10045 241.421725696403
2017 10045 318.593410228532
2018 10045 443.3983160078
2019 10045 483.12452005201
2010 10046 -99.2454333305359
2011 10046 42.3376306125096
2012 10046 71.8295436098769
2013 10046 90.7501822723432
2014 10046 133.500797046962
2015 10046 135.329324710063
2016 10046 223.211583482458
2017 10046 261.208083089193
2018 10046 409.256013000512
2019 10046 468.574509707364
2010 10047 -97.1618871688843
2011 10047 -1.06820678710938
2012 10047 20.5999549464746
2013 10047 5.93872594833374
2014 10047 134.559080774134
2015 10047 221.275759446621
2016 10047 203.30495039622
2017 10047 280.823856965995
2018 10047 304.591577597225
2019 10047 399.748709002112
Secondly, I tried to extract the max of (avg(nm)) for each year and corresponding herd and I tried this
SELECT
BYEAR, HERD, MAX(NM) AS MAX_NM
FROM
(SELECT
YEAR(FA_BDATE) AS BYEAR, FARM_FK HERD, AVG(NET_MERIT) AS NM
FROM
__FARM_ANALYTICS_TBL
GROUP BY
FARM_FK, YEAR(FA_BDATE)) AS AVGNM
GROUP BY
BYEAR
ORDER BY
BYEAR
Which does not work properly since I think according to what I need its wrong to group by HERD and also there are many HERD in previous select for each year. without HERD column in above query I get this which is correct but without corresponding herd id
2005 -258.71630859375
2006 -150.947634379069
2007 -127.1032270704
2008 -5.74109745025635
2009 -19.5938364664714
2010 -2.05634630137476
2011 64.6482777208895
2012 109.018188629743
2013 260.781127929688
2014 219.82367308171
2015 244.199884947291
2016 296.168976219786
2017 391.202879227419
2018 460.009900628413
2019 493.26334651952
I think you just want to use ROW_NUMBER():
SELECT hy.*
FROM (SELECT YEAR(FA_BDATE) AS BYEAR, FARM_FK AS HERD, AVG(NET_MERIT) AS NM,
ROW_NUMBER() OVER (PARTITION BY YEAR(FS_BDATE) ORDER BY AVG(NET_MERIT) DESC) as seqnum
FROM __FARM_ANALYTICS_TBL
GROUP BY FARM_FK, YEAR(FA_BDATE)
) hy
WHERE seqnum = 1
ORDER BY BYEAR;
Note that in the event of ties, this returns just one of the ties. If you want all of them, use RANK() instead of ROW_NUMBER().

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)

Oracle SQL Query -> Count 2 columns under 2 different conditions

I have a table that looks like this:
YEAR RESOLUTION_DATE CREATION_DATE
2013 2013/02/18
2012 2012/05/26
2009 2009/11/11
2013 2013/12/08 2013/12/01
2000 2000/17/31
2007 2007/12/08
2012 2012/12/08
2012 2012/03/23 2012/03/10
2012 2012/12/08
2007 2007/01/17
2012 2012/01/17 2012/01/10
2009 2009/02/14
I am trying to make a query that will output the following:
YEAR COUNT_RESOLUTION_DATE COUNT_CREATION_DATE
2000 0 1
2007 0 2
2009 0 2
2011 0 0
2012 2 5
2013 1 2
The caveat is that I would like the query to count the number of RESOLUTION_DATE by YEAR, where the RESOLUTION_DATE IS NOT NULL and i want to count ALL CREATION_DATE's. The SQL is needed for an oracle database.
Try this:
SELECT
COUNT(RESOLUTION_DATE) AS COUNT_RESOLUTION_DATE,
COUNT(CREATION_DATE) AS COUNT_CREATION_DATE
FROM MyTable
GROUP BY YEAR
ORDER BY YEAR
If you only want the non-NULL resolution dates counted, this should work:
SELECT
SUM(CASE WHEN RESOLUTION_DATE IS NULL THEN 0 ELSE 1 END) AS COUNT_RESOLUTION_DATE,
COUNT(CREATION_DATE) AS COUNT_CREATION_DATE
FROM MyTable
GROUP BY YEAR
ORDER BY YEAR;

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