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

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;

Related

SQL Count with rollup shows totals as NULL

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;

Detect and Set Column values between rows

I have a table relating to products:
PRD_SLD table
ID DATE SALE_IND
3 2012 0
3 2013 0
3 2014 1
3 2014 1
3 2015 1
3 2016 0
3 2017 1
I would like my final results to look like this:
PRD_SLD table
ID DATE SALE_IND STRT END
3 2012 0 2012 2014
3 2013 0 2012 2014
3 2014 1 2014 2016
3 2014 1 2014 2016
3 2015 1 2014 2016
3 2016 0 2016 2017
3 2017 1 2017 2017
I currently have a working CTE for retrieving the rows in which the values change. this CTE returns this:
PRD_SLD table
ID DATE SALE_IND
3 2012 0
3 2014 1
3 2016 0
3 2017 1
So it returns the first instance of the value in the table, and returns every time the SALE_IND changes.
Is there a way to create a start and end date based off of the date column? I am still very new to this and was enrolled in an advanced course. I'm sure there is a better way to complete this but is there a way to do it with the CTE results i have created? I know there is a between function but i don't know how to implement it into this query
One method is to define groups of adjacent records. You don't have a solid ordering of the rows, but you do have just enough information for this to work -- assuming the indicator is constant in each year.
select t.*,
min(year) over (partition by id, sale_ind, seqnum - seqnum_s) as min_year,
max(year) over (partition by id, sale_ind, seqnum - seqnum_s) as max_year
from (select t.*,
dense_rank() over (partition by id order by date) as seqnum,
dense_rank() over (partition by id, sale_ind order by date) as seqnum_s
from t
) t;

What is logical query proccessing taken by HAVING clause in SQL?

I'm pretty new in sql language, so I'm reading Sql Server 2012 T-SQL Fundamentals book to introduce myself in these topics. There are 2 examples that I'm trying to dissect to get a clear understanding about. First, the author execute the following query:
SELECT
empid,
YEAR(orderdate) AS orderyear,
SUM(freight) AS totalfreight,
COUNT(*) AS numorders
FROM
Sales.Orders
WHERE
custid = 71
GROUP BY
empid, YEAR(orderdate);
to obtain this:
empid orderyear totalfreight numorders
----------- ----------- --------------------- -----------
1 2006 126.56 1
2 2006 89.16 1
9 2006 214.27 1
1 2007 711.13 2
2 2007 352.69 1
3 2007 297.65 2
4 2007 86.53 1
5 2007 277.14 3
6 2007 628.31 3
7 2007 388.98 1
8 2007 371.07 4
1 2008 357.44 3
2 2008 672.16 2
4 2008 651.83 3
6 2008 227.22 1
7 2008 1231.56 2
But, in the 2nd example the author runs the following query:
SELECT
empid, YEAR(orderdate) AS orderyear
FROM
Sales.Orders
WHERE
custid = 71
GROUP BY
empid, YEAR(orderdate)
HAVING
COUNT(*) > 1;
This query returns the following output:
empid orderyear
----------- -----------
1 2007
3 2007
5 2007
6 2007
8 2007
1 2008
2 2008
4 2008
7 2008
My questions are:
Why is the resultset excluding 2006 years? and
why there are two rows with 1 values?
How HAVING clause does determine what rows return in both columns?
Thank you in advance.
In the first query, we see this:
COUNT(*) AS numorders
And in the second:
COUNT(*) > 1;
In the second query, this value isn't displayed, but we can use the first set of results to figure it out. All of these rows are not included in the second query:
empid orderyear totalfreight numorders
----------- ----------- --------------------- -----------
1 2006 126.56 1
2 2006 89.16 1
9 2006 214.27 1
2 2007 352.69 1
4 2007 86.53 1
7 2007 388.98 1
6 2008 227.22 1
Why?
Because numorders is only 1 and in the second query, we asked for rows where numorders > 1.
As to your question, HAVING is the version of WHERE that works on functions (such as COUNT()).
http://www.w3schools.com/sql/sql_having.asp
You use HAVING together with GROUP BY.
The criteria used in WHERE applies to all rows before aggregation, while HAVING applies to the aggregated results.
In other words: You have two criteria sections for filtering the dataset; before the grouping defined in WHERE, and after grouping defined in HAVING.

firebird sql order by

i got a dataset which looks like this:
customernumber year value
1 2011 500
2 2011 100
1 2010 400
3 2010 600
3 2011 300
2 2010 700
i want it to be ordered by highest value of year 2011, but the rows of each customer need to stay together.
it should look like this:
customernumber year value
1 2011 500
1 2010 400
3 2011 300
3 2010 600
2 2011 100
2 2010 700
is this even possible?
thanks in advance!
Use join to bring that value in, and then you can use it for the oder by:
select d.customernumber, d.year, d.value
from dataset d join
(select d.*
from dataset d
where d.year = 2011
) d2011
on d.customernumber = d2011.customernumber
order by d2011.value, d.customernumber, d.year desc;
In databases that support window functions, this can more easily be done as:
select d.*
from dataset d
order by max(case when year = 2011 then value end) over (partition by customernumber),
customernumber, year desc;
select customernumber, year, value from mytable
group by customernumber, year, value
order by year desc

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