SQL count and group by date and type - sql

I have a quality system table. There are 2 types of quality points NCR and RMA.
RMA is external and NCR is internal. We log transactions to the table either as a NCR or a RMA. I would like to have a query that will count all of the RMA's and all of the NCR's then group them by monthly count. For example:
MONTH RMA NCR
JANUARY 10 54
FEBRUARY 48 22
MARCH 25 55
If the value is zero for the month or the month has not yet come up, I don't want to see it on the report.
the table. this is what I have.
SELECT MONTH(QualityControl.CreateDate) MONTH, COUNT(*) AS 'NCR'
FROM QualityControl
WHERE YEAR(QualityControl.CreateDate)=2015
and
QualityControl.NCR is not null
GROUP BY MONTH(QualityControl.CreateDate)
This only gives me the month number (1=January) and the NCR count for that month.
Then I tried the following:
SELECT
SUM(CASE datepart(month,CreateDate) WHEN 1 THEN 1 ELSE 0 END) AS 'January',
SUM(CASE datepart(month,CreateDate) WHEN 2 THEN 1 ELSE 0 END) AS 'February',
SUM(CASE datepart(month,CreateDate) WHEN 3 THEN 1 ELSE 0 END) AS 'March',
SUM(CASE datepart(month,CreateDate) WHEN 4 THEN 1 ELSE 0 END) AS 'April',
SUM(CASE datepart(month,CreateDate) WHEN 5 THEN 1 ELSE 0 END) AS 'May',
SUM(CASE datepart(month,CreateDate) WHEN 6 THEN 1 ELSE 0 END) AS 'June',
SUM(CASE datepart(month,CreateDate) WHEN 7 THEN 1 ELSE 0 END) AS 'July',
SUM(CASE datepart(month,CreateDate) WHEN 8 THEN 1 ELSE 0 END) AS 'August',
SUM(CASE datepart(month,CreateDate) WHEN 9 THEN 1 ELSE 0 END) AS 'September',
SUM(CASE datepart(month,CreateDate) WHEN 10 THEN 1 ELSE 0 END) AS 'October',
SUM(CASE datepart(month,CreateDate) WHEN 11 THEN 1 ELSE 0 END) AS 'November',
SUM(CASE datepart(month,CreateDate) WHEN 12 THEN 1 ELSE 0 END) AS 'December',
SUM(CASE datepart(year,CreateDate) WHEN 2015 THEN 1 ELSE 0 END) AS 'TOTAL'
FROM
QualityControl
WHERE
CreateDate BETWEEN '2015/01/01' AND '2015/12/30'
And it gave me the count for NCR and RMA

Let's go with your first attempt, which is one row per value. You want to count the valid "NCR" and "RMA" values. You can use a COUNT() like this:
SELECT MONTH(qc.CreateDate) as MON, COUNT(NCR) as NCR, COUNT(RMA) as RMA
FROM QualityControl qc
WHERE CreateDate >= '2015-01-01' AND CreateDate < '2016-01-01'
GROUP BY MONTH(qc.CreateDate)
ORDER BY MON;
With a column (or other expression), COUNT() counts the number of non-NULL values. That seems to be exactly what you want.
If you wanted the SUM() of the values, then you would use SUM() instead of COUNT().
Note about the dates:
The version using comparisons is better than the one using YEAR(), because it can make use of indexes.
I changed the BETWEEN to >= and <. This version works correctly, if your date/time column has a time component. It also works for dates.
December has 31 days.

in sql server you can do all of these :
SELECT
CASE datepart(month,getdate()) WHEN 1 THEN 1 ELSE 0 END AS January,
CASE datepart(month,getdate()) WHEN 2 THEN 1 ELSE 0 END AS "February",
CASE datepart(month,getdate()) WHEN 3 THEN 1 ELSE 0 END AS [March]
the best method would be
SELECT datename(month, getdate())

Related

SQL Query to categorize results of separate query

I am trying to run a query on the results of a separate query to update the Route_Type column for each record based on unique Route_Code and Delivery_Day. For each distinct Route_Code from the select query, the Route_Type should be updated based on the following logic:
if there are no records for a specific Route_Code where Delivery_Day = 'Mon' then Route_Type should update to 'A'
if there are no records for a specific Route_Code where Delivery_Day = 'Sat' then Route_Type should update to 'B'
If there are no records for a specific Route_Code where Delivery_Day = 'Mon' OR 'Sat' then Route_Type should be 'TBD'
Else Route_Type = 'Both.'
Data:
Record Route_Code Delivery_Day Route_Type
1 112 Mon
2 112 Thur
3 112 Sat
4 112 Sun
5 113 Tue
6 113 Fri
7 113 Sat
8 113 Sun
9 113 Wed
Select Query:
Select Distinct Route_Code
From Deliveries;
Results:
Route_Code
1 112
2 113
The query should return all unique Route_Code and the calculated Route_Type for each, shown below...
Desired Query Result:
Route_Code Route_Type
1 112 Both
2 113 A
As a follow-up, I want all Route_Codes that have fewer than 1 month of records to display 'TBD.' The logic I have so far is
When
Max(sum(case when Delivery_Day= 'Mon' then 1 else 0 end),
sum(case when Delivery_Day= 'Tue' then 1 else 0 end),
sum(case when Delivery_Day= 'Wed' then 1 else 0 end),
sum(case when Delivery_Day= 'Thu' then 1 else 0 end),
sum(case when Delivery_Day= 'Fri' then 1 else 0 end),
sum(case when Delivery_Day= 'Sat' then 1 else 0 end),
sum(case when Delivery_Day= 'Sun' then 1 else 0 end)
Then 'TBD'
I realize that the native Max() function handles only single arguments, and am wondering where to go from here.
This sounds like aggregation. I find your logic a bit hard to follow. If I understand correctly, "B" has a Monday delivery and "A" has a Saturday. The logic looks like this:
select route_code,
(case when sum(case when Delivery_Day = 'Mon' then 1 else 0 end) > 0 and
sum(case when Delivery_Day = 'Sat' then 1 else 0 end) > 0
then 'Both'
when sum(case when Delivery_Day = 'Mon' then 1 else 0 end) > 0
then 'B'
when sum(case when Delivery_Day = 'Sat' then 1 else 0 end) > 0
then 'A'
else 'TBD'
end) as route_type
from delivies
group by route_code

Is it possible to Count by diffrent condition in one query?

I have a Shipments table which basicly contains Shipments data with dates
id is integer
dateshipped is date
id dateshipped
1 1-JAN-16
2 1-JAN-16
3 3-FEB-16
4 9-FEB-16
I want to write a query which count all shipments based on Months.
What I should get is:
Jan Feb March....
2 2 0
I know I can do it by having query for each column, get only relevent rows for this specific month and just count them.
As follows:
Select (Select count(*)
from Shipments
Where EXTRACT(YEAR FROM dateshipped)::int=2016 and EXTRACT(MONTH FROM dateshipped)::int=1 )as JAN,
(Select count(*)
from Shipments
Where EXTRACT(YEAR FROM dateshipped)::int=2016 and EXTRACT(MONTH FROM dateshipped)::int=2 )as FEB
This works however its too much of the same code...
I am wondring if it is possible to do it with a single FROM statment and each column get it's own relevent rows for count.
Something like:
Select COL1,COL2,COL3...
from Shipments
Where EXTRACT(YEAR FROM dateshipped)::int=2016;
and have something like:
COL1 = count only JAN records
COL2 = count only FEB records
....
maybe there is something with Parations on months or any other solution?
You need a pivot query to accomplish this:
SELECT SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 1 THEN 1 ELSE 0 END) AS Jan,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 2 THEN 1 ELSE 0 END) AS Feb,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 3 THEN 1 ELSE 0 END) AS Mar,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 4 THEN 1 ELSE 0 END) AS Apr,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 5 THEN 1 ELSE 0 END) AS May,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 6 THEN 1 ELSE 0 END) AS Jun,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 7 THEN 1 ELSE 0 END) AS Jul,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 8 THEN 1 ELSE 0 END) AS Aug,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 9 THEN 1 ELSE 0 END) AS Sep,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 10 THEN 1 ELSE 0 END) AS Oct,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 11 THEN 1 ELSE 0 END) AS Nov,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 12 THEN 1 ELSE 0 END) AS Dec
FROM Shipments
WHERE EXTRACT(YEAR FROM dateshipped)::int=2016
Since 9.4 you can use FILTER
SELECT
count(*) AS total,
count(*) FILTER (WHERE Extract(MONTH FROM dateshipped)::int=1) AS JAN,
count(*) FILTER (WHERE Extract(MONTH FROM dateshipped)::int=2) AS FEB,
...
FROM Shipments
WHERE Extract(YEAR FROM dateshipped)::int=2016;
Try case with sum function:
Select
sum(case when extract(MONTH from dateshipped)=1 then 1 else 0 end) as jan,
sum(case when extract(MONTH from dateshipped)=2 then 1 else 0 end) as feb,
sum(case when extract(MONTH from dateshipped)=3 then 1 else 0 end) as march
.....
.....
from Shipments
Where EXTRACT(YEAR FROM dateshipped)::int=2016;

SQL Grand Total last ROW

Is there a way I could get the grand total of each month. I've looked into Rollup but cant seem to figure it out.
Query I have is
SELECT t.city,f.fname,f.lname,
SUM(CASE datepart(month,ddate) WHEN 1 THEN 1 ELSE 0 END) AS 'January',
SUM(CASE datepart(month,ddate) WHEN 2 THEN 1 ELSE 0 END) AS 'February',
SUM(CASE datepart(month,ddate) WHEN 3 THEN 1 ELSE 0 END) AS 'March',
SUM(CASE datepart(month,ddate) WHEN 4 THEN 1 ELSE 0 END) AS 'April',
SUM(CASE datepart(month,ddate) WHEN 5 THEN 1 ELSE 0 END) AS 'May',
SUM(CASE datepart(month,ddate) WHEN 6 THEN 1 ELSE 0 END) AS 'June',
SUM(CASE datepart(month,ddate) WHEN 7 THEN 1 ELSE 0 END) AS 'July',
SUM(CASE datepart(month,ddate) WHEN 8 THEN 1 ELSE 0 END) AS 'August',
SUM(CASE datepart(month,ddate) WHEN 9 THEN 1 ELSE 0 END) AS 'September',
SUM(CASE datepart(month,ddate) WHEN 10 THEN 1 ELSE 0 END) AS 'October',
SUM(CASE datepart(month,ddate) WHEN 11 THEN 1 ELSE 0 END) AS 'November',
SUM(CASE datepart(month,ddate) WHEN 12 THEN 1 ELSE 0 END) AS 'December',
SUM(CASE datepart(year,ddate) WHEN 2014 THEN 1 ELSE 0 END) AS 'TOTAL'
from world T
INNER JOIN sales F ON T.ID=F.ID
where t.city = ROME
group by t.city,f.fname,f.lname
Output example
t.city, f.fname, f.lname January total
ROME John Doe 5 5
Grand Total 5 5
Did you try this?
group by GROUPING SETS((t.city, f.fname, f.lname), ())
To get Grand Total you'll need to change the select as well.
And, as a note: use single quotes only for string and date constants. Using them for column identifiers can lead to confusing and problems. Either drop the quotes altogether or use square braces or double quotes.
EDIT:
Without group by extensions or CTEs this is a pain. There is a trick to doing it with minimal modifications:
SELECT (case when which = 'normal' then t.city else 'Grand Total' end),
(case when which = 'normal' then f.fname end),
(case when which = 'normal' then f.lname end),
SUM(CASE datepart(month,ddate) WHEN 1 THEN 1 ELSE 0 END) AS 'January',
SUM(CASE datepart(month,ddate) WHEN 2 THEN 1 ELSE 0 END) AS 'February',
SUM(CASE datepart(month,ddate) WHEN 3 THEN 1 ELSE 0 END) AS 'March',
SUM(CASE datepart(month,ddate) WHEN 4 THEN 1 ELSE 0 END) AS 'April',
SUM(CASE datepart(month,ddate) WHEN 5 THEN 1 ELSE 0 END) AS 'May',
SUM(CASE datepart(month,ddate) WHEN 6 THEN 1 ELSE 0 END) AS 'June',
SUM(CASE datepart(month,ddate) WHEN 7 THEN 1 ELSE 0 END) AS 'July',
SUM(CASE datepart(month,ddate) WHEN 8 THEN 1 ELSE 0 END) AS 'August',
SUM(CASE datepart(month,ddate) WHEN 9 THEN 1 ELSE 0 END) AS 'September',
SUM(CASE datepart(month,ddate) WHEN 10 THEN 1 ELSE 0 END) AS 'October',
SUM(CASE datepart(month,ddate) WHEN 11 THEN 1 ELSE 0 END) AS 'November',
SUM(CASE datepart(month,ddate) WHEN 12 THEN 1 ELSE 0 END) AS 'December',
SUM(CASE datepart(year,ddate) WHEN 2014 THEN 1 ELSE 0 END) AS 'TOTAL'
from world T INNER JOIN
sales F
ON T.ID=F.ID cross join
(select 'normal' as which union all select 'total') as which
where t.city = ROME
group by (case when which = 'normal' then t.city else 'Grand Total' end),
(case when which = 'normal' then f.fname end),
(case when which = 'normal' then f.lname end);
(I'm not reformatting the rest of the query, but you should not use single quotes for column identifiers. Only use single quotes for string and date constants.)
Edit: Using GROUP BY ROLLUP(grouping columns) this will calculate the sum of the aggregated columns. By default it will return 'NULL' for all grouped columns but you can put an ISNULL wrapper around to get rid of it, or return a specific value.
SELECT ISNULL(t.city, 'Grand Total') AS [City],f.fname AS [Fname],f.lname AS [Lname],
SUM(CASE datepart(month,ddate) WHEN 1 THEN 1 ELSE 0 END) AS [January],
SUM(CASE datepart(month,ddate) WHEN 2 THEN 1 ELSE 0 END) AS [February],
SUM(CASE datepart(month,ddate) WHEN 3 THEN 1 ELSE 0 END) AS [March],
SUM(CASE datepart(month,ddate) WHEN 4 THEN 1 ELSE 0 END) AS [April],
SUM(CASE datepart(month,ddate) WHEN 5 THEN 1 ELSE 0 END) AS [May],
SUM(CASE datepart(month,ddate) WHEN 6 THEN 1 ELSE 0 END) AS [June],
SUM(CASE datepart(month,ddate) WHEN 7 THEN 1 ELSE 0 END) AS [July],
SUM(CASE datepart(month,ddate) WHEN 8 THEN 1 ELSE 0 END) AS [August],
SUM(CASE datepart(month,ddate) WHEN 9 THEN 1 ELSE 0 END) AS [September],
SUM(CASE datepart(month,ddate) WHEN 10 THEN 1 ELSE 0 END) AS [October],
SUM(CASE datepart(month,ddate) WHEN 11 THEN 1 ELSE 0 END) AS [November],
SUM(CASE datepart(month,ddate) WHEN 12 THEN 1 ELSE 0 END) AS [December],
SUM(CASE datepart(year,ddate) WHEN 2014 THEN 1 ELSE 0 END) AS [TOTAL]
FROM world T
INNER JOIN sales F ON T.ID=F.ID
WHERE t.city = ROME
GROUP BY ROLLUP(t.city,f.fname,f.lname)

Group by year in sql

I am trying to group by year but was not able to do.I can get the column count but not year wise. this is what i tried.
select t_contract ,
sum(CASE t_contract when '18' then 1 else 0 end) as XL,
sum(CASE t_contract when '01' then 1 else 0 end) as VC,
sum(CASE t_contract when '75' then 1 else 0 end) as AN,
sum(CASE t_contract when '48' then 1 else 0 end) as CS
from icps.dbo.tickets
WHERE
t_date_time_issued >= DATEADD(year, -6, GETDATE())
GROUP BY contract
.. but i want to add year .. where i have t_date_time _issued column.
My another query is I have a column called t_zone_name and I want to sum all the rows where t_zone_anme like '%ICeland%' an i tried this:
sum(CASE t_zone_name like '%ICeland%' then 1 else 0 end) as ICELAND
but I get an error on statement like... thanks in advance.
LIKE
YEAR XL VC AN CS total
2010 50 50 50 50 200
2011 5 5 5 5 20
Try the below query:
SELECT t_contract, YEAR(t_date_time_issued) As Yr, SUM(CASE WHEN t_zone_name like '%ICeland%' THEN 1 ELSE 0 END) AS ICELAND
SUM(CASE t_contract when '18' then 1 else 0 end) as XL,
SUM(CASE t_contract when '01' then 1 else 0 end) as VC,
SUM(CASE t_contract when '75' then 1 else 0 end) as AN,
SUM(CASE t_contract when '48' then 1 else 0 end) as CS
FROM icps.dbo.tickets
WHERE YEAR(t_date_time_issued) >= (YEAR(GetDate()) - 6)
GROUP BY t_contract, YEAR(t_date_time_issued)
You might need change the order of t_contract and YEAR(t_date_time_issued) depending on which grouping you want to apply first.
As suggested by #ray I have replaced DATEPART(yyyy, t_date_time_issued) >= DATEPART(yyyy, DATEADD(year, -6, GETDATE())) with year(t_date_time_issued) >= (year(GetDate()) - 6)
If you want to group by year, in sql server, you might
GROUP BY DATEDIFF(year,t_date_time_issued, GETDATE())
In other DB engine, usually has method to get year part, or use substring to get year part from a time string.

Count records for every month in a year

I have a table with total no of 1000 records in it.It has the following structure:
EMP_ID EMP_NAME PHONE_NO ARR_DATE
1 A 545454 2012/03/12
I want to calculate no of records for every month in year-2012
Is there any way that should solve my issue in a single shot?
I tried:
select count(*)
from table_emp
where year(ARR_DATE) = '2012' and month(ARR_DATE) = '01'
SELECT COUNT(*)
FROM table_emp
WHERE YEAR(ARR_DATE) = '2012'
GROUP BY MONTH(ARR_DATE)
This will give you the count per month for 2012;
SELECT MONTH(ARR_DATE) MONTH, COUNT(*) COUNT
FROM table_emp
WHERE YEAR(arr_date)=2012
GROUP BY MONTH(ARR_DATE);
Demo here.
Try This query:
SELECT
SUM(CASE datepart(month,ARR_DATE) WHEN 1 THEN 1 ELSE 0 END) AS 'January',
SUM(CASE datepart(month,ARR_DATE) WHEN 2 THEN 1 ELSE 0 END) AS 'February',
SUM(CASE datepart(month,ARR_DATE) WHEN 3 THEN 1 ELSE 0 END) AS 'March',
SUM(CASE datepart(month,ARR_DATE) WHEN 4 THEN 1 ELSE 0 END) AS 'April',
SUM(CASE datepart(month,ARR_DATE) WHEN 5 THEN 1 ELSE 0 END) AS 'May',
SUM(CASE datepart(month,ARR_DATE) WHEN 6 THEN 1 ELSE 0 END) AS 'June',
SUM(CASE datepart(month,ARR_DATE) WHEN 7 THEN 1 ELSE 0 END) AS 'July',
SUM(CASE datepart(month,ARR_DATE) WHEN 8 THEN 1 ELSE 0 END) AS 'August',
SUM(CASE datepart(month,ARR_DATE) WHEN 9 THEN 1 ELSE 0 END) AS 'September',
SUM(CASE datepart(month,ARR_DATE) WHEN 10 THEN 1 ELSE 0 END) AS 'October',
SUM(CASE datepart(month,ARR_DATE) WHEN 11 THEN 1 ELSE 0 END) AS 'November',
SUM(CASE datepart(month,ARR_DATE) WHEN 12 THEN 1 ELSE 0 END) AS 'December',
SUM(CASE datepart(year,ARR_DATE) WHEN 2012 THEN 1 ELSE 0 END) AS 'TOTAL'
FROM
sometable
WHERE
ARR_DATE BETWEEN '2012/01/01' AND '2012/12/31'
select count(*)
from table_emp
where DATEPART(YEAR, ARR_DATE) = '2012' AND DATEPART(MONTH, ARR_DATE) = '01'