Embedded Case statement - sql

I have a query (which works) however, I want to be able to make it so I don't need to rerun the query to change the date ranges.
What I have here is it is pulling customer name and the amount and summing it. I need it broken down monthly by fiscal year, so what I would just do is change the year and rerun it, but I want to make the query more efficient so it doesn't need to be changed in the future (except the end date for a new FY) So after it takes the sum of each month (July to June), I want it to show the FY. So the date ranges from 2014 to 2015 should show a column called FY and have 2015 in the column. I am pretty certain I am on the right track but not there. I only showed what I was working on for the first case (which will be replicated for the other cases)
Could this just be an IF statement loop instead of another case statement? Any help with direction would be great to help me learn. I got this far, but just want to make the code more efficient for someone to use
Declare #StartDate datetime
Declare #EndDate datetime
set #StartDate = convert(datetime, '07/01/2014')
set #EndDate = convert(datetime, '06/30/2017')
select
d.CUSTNMBR Customer_ID,
d.CUSTNAME Customer_Name,
'A' as Company,
sum(case when month(d.DOCDATE) = 7
then d.SALES else 0 end) July,
case when datetime between '07/01/2016' and '06/30/2017' as '2017'
when datetime between '07/01/2015' and '06/30/2016' as '2016'
when datetime between '07/01/2014' and '06/30/2015' as '2015'
END
sum(case when month(d.DOCDATE) = 8
then d.SALES else 0 end) August,
sum(case when month(d.DOCDATE) = 9
then d.SALES else 0 end) September,
sum(case when month(d.DOCDATE) = 10
then d.SALES else 0 end) October,
sum(case when month(d.DOCDATE) = 11
then d.SALES else 0 end) November,
sum(case when month(d.DOCDATE) = 12
then d.SALES else 0 end) December,
sum(case when month(d.DOCDATE) = 1
then d.SALES else 0 end) January,
sum(case when month(d.DOCDATE) = 2
then d.SALES else 0 end) February,
sum(case when month(d.DOCDATE) = 3
then d.SALES else 0 end) March,
sum(case when month(d.DOCDATE) = 4
then d.SALES else 0 end) April,
sum(case when month(d.DOCDATE) = 5
then d.SALES else 0 end) May,
sum(case when month(d.DOCDATE) = 6
then d.SALES else 0 end) June,
sum(d.SALES) 'Year to Date'
from
(select s.DOCDATE, s.CUSTNMBR, c.CUSTNAME,
case s.SOPTYPE
when 3 then s.DOCAMNT
when 4 then s.DOCAMNT*-1
end SALES
from a1.dbo.S200 s
left outer join a1.dbo.RM1 c
on s.CUSTNMBR = c.CUSTNMBR
where s.VOIDSTTS = 0
and s.SOPTYPE in (3,4) and
s.DOCDATE between #StartDate and #EndDate -- Fiscal Year
) d
group by d.CUSTNMBR, d.CUSTNAME

Consider a recursive CTE that iterates through each fiscal year and then run a CROSS JOIN...WHERE (CROSS APPLY can work too) on your existing derived table. The WHERE conditions DOCDate to fiscal year start and end ranges. And going forward, simply change the declaration lines for each fiscal year. In fact, you can set up #end INT = 2020 to anticipate future data!
DECLARE #start INT = 2014;
DECLARE #end INT = 2016;
WITH fiscalyears AS (
SELECT #start + 1 AS FY,
CONVERT(datetime, cast(1 as varchar)+'/'+cast(7 as varchar)+'/'+cast(#start as varchar), 103) As StartRng,
CONVERT(datetime, cast(30 as varchar)+'/'+cast(6 as varchar)+'/'+cast(#start + 1 as varchar), 103) As EndRng
UNION ALL
SELECT FY + 1,
CONVERT(datetime, cast(1 as varchar)+'/'+cast(7 as varchar)+'/'+cast(FY + 1 as varchar), 103),
CONVERT(datetime, cast(30 as varchar)+'/'+cast(6 as varchar)+'/'+cast(FY + 2 as varchar), 103)
FROM fiscalyears
WHERE FY < #end
)
-- FY StartRng EndRng
-- 2015 2014-07-01 00:00:00.000 2015-06-30 00:00:00.000
-- 2016 2015-07-01 00:00:00.000 2016-06-30 00:00:00.000
---2017 2016-07-01 00:00:00.000 2017-06-30 00:00:00.000
select
d.CUSTNMBR Customer_ID,
d.CUSTNAME Customer_Name,
'A' as Company,
d.FY As FY,
sum(case when month(d.DOCDATE) = 7 then d.SALES else 0 end) AS July,
sum(case when month(d.DOCDATE) = 8 then d.SALES else 0 end) AS August,
sum(case when month(d.DOCDATE) = 9 then d.SALES else 0 end) AS September,
sum(case when month(d.DOCDATE) = 10 then d.SALES else 0 end) AS October,
sum(case when month(d.DOCDATE) = 11 then d.SALES else 0 end) AS November,
sum(case when month(d.DOCDATE) = 12 then d.SALES else 0 end) AS December,
sum(case when month(d.DOCDATE) = 1 then d.SALES else 0 end) AS January,
sum(case when month(d.DOCDATE) = 2 then d.SALES else 0 end) AS February,
sum(case when month(d.DOCDATE) = 3 then d.SALES else 0 end) AS March,
sum(case when month(d.DOCDATE) = 4 then d.SALES else 0 end) AS April,
sum(case when month(d.DOCDATE) = 5 then d.SALES else 0 end) AS May,
sum(case when month(d.DOCDATE) = 6 then d.SALES else 0 end) AS June,
sum(d.SALES) 'Year to Date'
from
(select f.FY, s.DOCDATE, s.CUSTNMBR, c.CUSTNAME,
case s.SOPTYPE
when 3 then s.DOCAMNT
when 4 then s.DOCAMNT*-1
end SALES
from a1.dbo.S200 s
left outer join a1.dbo.RM1 c
on s.CUSTNMBR = c.CUSTNMBR
cross join fiscalyears f
where s.VOIDSTTS = 0
and s.SOPTYPE in (3,4)
and s.DOCDATE between f.StartRng and f.EndRng) d
group by d.CUSTNMBR,
d.CUSTNAME,
d.FY

Do you have access to create functions? If so, create a (re-usable) scalar function for FY. E.g.:
CREATE FUNCTION dbo.FY (input_date as smalldatetime)
RETURNS int
BEGIN
DECLARE #return int
SET #return = year(input_date)
IF month(input_date) <= 6
#return = #return + 1
RETURN #return
END
Then Use the function in your SELECT...
SELECT
...,
FY(d.DOCDATE),
...
FROM
...
Otherwise, you can inline the function -- e.g.:
SELECT
...,
CASE WHEN Month(d.DOCDATE) <= 6 THEN 1 ELSE 0 END + year(d.DOCDATE) as FY
...
Also worth mentioning -- it looks like you're naming your Months the hard way.
Try this instead:
DATENAME(month,d.DOCDATE),
Also...
Suggest keeping your query's data and layout separated a bit more (for example, where you're create a horizontal layout for your months) -- you might like what PIVOT (https://technet.microsoft.com/en-us/library/ms177410(v=sql.105).aspx) can do for you...
If you do this, you can keep your query's data a little cleaner -- and then use it's output in other queries as well. More re-usability = less work for you! :-)

I am proposing that the S200 table shall have computed columns as helper like this:
create table S200
(
CUSTNMBR varchar(10) null,
DOCDATE date null,
SOPTYPE int null,
DOCAMNT money null,
FISCALYEAR as datepart(year, DOCDATE) +
case when datepart(month, DOCDATE) >= 7 then 1 else 0 end,
FISCALMONTHNAME as (datename(month, DOCDATE))
)
Then we can simply PIVOT it like:
select
*,
isnull([January], 0) +
isnull([February], 0) +
isnull([March], 0) +
isnull([April], 0) +
isnull([May], 0) +
isnull([June], 0) +
isnull([July], 0) +
isnull([August], 0) +
isnull([September], 0) +
isnull([October], 0) +
isnull([November], 0) +
isnull([December], 0) as YearToDate
from
(
select
s.CUSTNMBR,
s.FISCALYEAR,
FISCALMONTHNAME,
case s.SOPTYPE
when 3 then s.DOCAMNT
when 4 then -s.DOCAMNT
end as SALES
from
S200 as s
)
as d
pivot
(
sum
(
d.SALES
)
for d.FISCALMONTHNAME in
(
[January],
[February],
[March],
[April],
[May],
[June],
[July],
[August],
[September],
[October],
[November],
[December]
)
)
as p
order by 2, 1
If you have a Tally table, you can mock populate S200 for 3 years starts from 2014 for 3 customers:
truncate table S200
insert
S200
select
101 + cast(3 * rand(checksum(newid())) as int),
dateadd(day, cast(3 * 365 * rand(checksum(newid())) as int),
datefromparts(2014, 1, 1)),
case when rand(checksum(newid())) > .6 then 4 else 3 end,
1 + cast(100 * rand(checksum(newid())) as int)
from
Tally
where
Id <= 1000
You may have result like this:
| CUSTNMBR | FISCALYEAR | January | February | March | April | May | June | July | August | September | October | November | December | YearToDate |
|----------|------------|---------|----------|---------|--------|---------|---------|---------|---------|-----------|---------|----------|----------|------------|
| 101 | 2014 | 160.00 | 143.00 | 139.00 | 28.00 | 247.00 | 28.00 | NULL | NULL | NULL | NULL | NULL | NULL | 745.00 |
| 102 | 2014 | 24.00 | 158.00 | -244.00 | -85.00 | 103.00 | 20.00 | NULL | NULL | NULL | NULL | NULL | NULL | -24.00 |
| 103 | 2014 | 123.00 | -167.00 | -6.00 | -30.00 | -53.00 | 15.00 | NULL | NULL | NULL | NULL | NULL | NULL | -118.00 |
| 101 | 2015 | 14.00 | 200.00 | 304.00 | 137.00 | 236.00 | -245.00 | 289.00 | 258.00 | 192.00 | -13.00 | 275.00 | 9.00 | 1656.00 |
| 102 | 2015 | -40.00 | 115.00 | -36.00 | 142.00 | -18.00 | 48.00 | -262.00 | -71.00 | 24.00 | 189.00 | -166.00 | -49.00 | -124.00 |
| 103 | 2015 | 265.00 | -103.00 | 73.00 | -50.00 | 61.00 | -268.00 | -20.00 | -214.00 | -21.00 | 50.00 | -48.00 | -204.00 | -479.00 |
| 101 | 2016 | 207.00 | -201.00 | 34.00 | 397.00 | -156.00 | 267.00 | -272.00 | -156.00 | -61.00 | -98.00 | 575.00 | 107.00 | 643.00 |
| 102 | 2016 | 27.00 | 20.00 | 199.00 | 328.00 | 44.00 | 55.00 | 447.00 | 188.00 | -57.00 | -118.00 | -1.00 | 74.00 | 1206.00 |
| 103 | 2016 | -114.00 | 333.00 | 299.00 | 145.00 | 80.00 | -8.00 | 58.00 | -151.00 | 44.00 | 799.00 | 218.00 | 14.00 | 1717.00 |
| 101 | 2017 | NULL | NULL | NULL | NULL | NULL | NULL | -154.00 | -56.00 | 192.00 | -283.00 | 371.00 | 155.00 | 225.00 |
| 102 | 2017 | NULL | NULL | NULL | NULL | NULL | NULL | 11.00 | -50.00 | 82.00 | 8.00 | 562.00 | -26.00 | 587.00 |
| 103 | 2017 | NULL | NULL | NULL | NULL | NULL | NULL | 294.00 | -93.00 | -51.00 | 29.00 | 322.00 | 392.00 | 893.00 |
Perhaps with certain indexes on those computed columns, it would give even better performance.

Related

SQL last 15 months of sales grouped by customer

I would like to output in sql a table that contains the monthly sales per customer. Each column should correspond to another month.
First column should be current month example my sql columns are:
customer
invoicedate
sales
Original table looks like this:
+------------+------------+---------+
| Customer | invdate | sales |
+------------+------------+---------+
| Best Buy | 03-12-2019 | 433 |
| Walmart | 03-15-2019 | 543 |
| Home Depot | 12-12-2018 | 32 |
+------------+------------+---------+
Desired Output:
+------------+----------+--------+--------+--------+--------+----------+
| Customer | March 19 | Feb 19 | Jan 19 | Dec 18 | Nov 18 | Oct 18 |
+------------+----------+--------+--------+--------+--------+----------+
| Home Depot | 100 | 300 | 244 | 32 | 322 | 43 |
| Walmart | 543 | 222 | 234 | 12 | 234 | 34 |
| Bestbuy | 433 | 323 | 323 | 23 | 433 | 34 |
+------------+----------+--------+--------+--------+--------+----------+
You can use group by, sum, and case to good effect, like this:
select
customer,
sum(case when year(invdate) = year(getdate) and month(invdate) = month(getdate()) then sales else o end),
sum(case when year(invdate) = year(dateadd(m,1,getdate))
and month(invdate) = month(dateadd(m,1,getdate())) then sales else o end),
sum(case when year(invdate) = year(dateadd(m,2,getdate))
and month(invdate) = month(dateadd(m,2,getdate())) then sales else o end),
sum(case when year(invdate) = year(dateadd(m,3,getdate))
and month(invdate) = month(dateadd(m,3,getdate())) then sales else o end),
sum(case when year(invdate) = year(dateadd(m,4,getdate))
and month(invdate) = month(dateadd(m,4,getdate())) then sales else o end),
sum(case when year(invdate) = year(dateadd(m,5,getdate))
and month(invdate) = month(dateadd(m,5,getdate())) then sales else o end)
from tableyoudidnotgivethenameof
group by customer

how to get current employees status,resigned status,newly joined status in particular period?

I have employee master table in this table have empcode,empname,joindate,resigndate but not mention any date for entry in master.
How to get current employees,no of employees resigned,no of employees joined in particular date periods
for ex:
current employees -200
resigned employees -25
joined employees -10
current status -200+10=210-25=185
this every i wanted in table format
If we have a calendar table or date dimension, query, view... etc, this becomes much simpler.
/* example Calendar, just Months */
create table dbo.Calendar(
MonthStart date primary key
, MonthEnd date
);
declare #FromDate date = '20000101';
declare #ThruDate date = '20301201';
with n as (select n from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) t(n))
, d as (
select DateValue=convert(date,dateadd(month
, row_number() over (order by (select 1)) -1, #fromdate))
from n as deka
cross join n as hecto
cross join n as kilo
)
insert into dbo.Calendar
select top (datediff(month, #FromDate, #ThruDate)+1)
MonthStart = dateadd(month, datediff(month, 0, DateValue), 0)
, MonthEnd = dateadd(day,-1, dateadd(month, datediff(month, 0, DateValue)+1, 0))
from d
order by DateValue;
Query using a common table expression and then sum(case when.. 1 else 0 end)
;with cte as (
select
c.MonthStart
, c.MonthEnd
, e.EmpCode
, e.JoinDate
, e.ResignDate
from dbo.Calendar as c
inner join dbo.EmpMaster as e
on c.MonthEnd >= e.JoinDate
and c.MonthStart <= e.ResignDate
)
select
MonthStart
, MonthEnd
, CurrentEmployees = sum(
case when JoinDate < MonthStart
then 1 else 0 end )
, Joined = sum(
case when JoinDate >= MonthStart and JoinDate <= MonthEnd
then 1 else 0 end)
, Resigned = sum(
case when ResignDate >= MonthStart and ResignDate <= MonthEnd
then 1 else 0 end)
, CurrentStatus = sum(
case when ResignDate > MonthEnd
then 1 else 0 end)
from cte
group by
cte.MonthStart
, cte.MonthEnd
order by cte.MonthStart;
without the cte, and using count(case when ... then column else null end) instead:
select
MonthStart
, MonthEnd
, CurrentEmployees = count (
case when JoinDate < MonthStart
then EmpCode else null end )
, Joined = count (
case when JoinDate >= MonthStart and JoinDate <= MonthEnd
then EmpCode else null end )
, Resigned = count (
case when ResignDate >= MonthStart and ResignDate <= MonthEnd
then EmpCode else null end )
, CurrentStatus = count (
case when ResignDate > MonthEnd
then EmpCode else null end )
from (
select
c.MonthStart
, c.MonthEnd
, e.EmpCode
, e.JoinDate
, e.ResignDate
from dbo.Calendar as c
inner join dbo.EmpMaster as e
on c.MonthEnd >= e.JoinDate
and c.MonthStart <= e.ResignDate
) as cte
group by cte.MonthStart, cte.MonthEnd
order by cte.MonthStart
Each returns the same results: http://rextester.com/AEZTL76069
+------------+------------+------------------+--------+----------+---------------+
| MonthStart | MonthEnd | CurrentEmployees | Joined | Resigned | CurrentStatus |
+------------+------------+------------------+--------+----------+---------------+
| 2010-01-01 | 2010-01-31 | 0 | 3 | 0 | 3 |
| 2010-02-01 | 2010-02-28 | 3 | 1 | 0 | 4 |
| 2010-03-01 | 2010-03-31 | 4 | 2 | 0 | 6 |
| 2010-04-01 | 2010-04-30 | 6 | 1 | 0 | 7 |
| 2010-05-01 | 2010-05-31 | 7 | 2 | 0 | 9 |
| 2010-06-01 | 2010-06-30 | 9 | 1 | 0 | 10 |
| 2010-07-01 | 2010-07-31 | 10 | 1 | 0 | 11 |
| 2010-08-01 | 2010-08-31 | 11 | 2 | 0 | 13 |
| 2010-09-01 | 2010-09-30 | 13 | 6 | 0 | 19 |
| 2010-10-01 | 2010-10-31 | 19 | 2 | 0 | 21 |
| 2010-11-01 | 2010-11-30 | 21 | 1 | 0 | 22 |
| 2010-12-01 | 2010-12-31 | 22 | 0 | 0 | 22 |
+------------+------------+------------------+--------+----------+---------------+

Need a select query to get the output as shown below.?

I Have a SQL Table as shown below,
| Loc | Date | Id | Sts |
-------------------------
| Hyd | 15-01-2016 | 1 | A |
| Vjd | 16-01-2016 | 2 | B |
| Viz | 15-01-2016 | 3 | C |
| Hyd | 15-03-2016 | 4 | A |
| Vjd | 15-03-2016 | 5 | B |
| Viz | 15-03-2016 | 6 | C |
| Hyd | 15-03-2016 | 4 | A |
| Vjd | 15-05-2016 | 5 | B |
| Viz | 15-05-2016 | 6 | C |
And i need output like,
**| Loc | Jan-16 | Mar-16 | May-16 |**
**|-------|A |B |C |A |B |C |A |B |C |**
----------
|Hyd | 1 | 0 | 0 | 2 | 0 | 0 | 0 | 0 | 0 |
|Vjd | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 0 |
|Viz | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 1 |
Can anyone help me out please..
Thanks in Advance.
You will basically need to aggregate based on CASE statements, like this:
DECLARE #table TABLE (loc VARCHAR(3), [date] DATE, id INT, sts CHAR(1));
INSERT INTO #table SELECT 'Hyd', '20160115', 1, 'A';
INSERT INTO #table SELECT 'Vjd', '20160116', 2, 'B';
INSERT INTO #table SELECT 'Viz', '20160115', 3, 'C';
INSERT INTO #table SELECT 'Hyd', '20160315', 4, 'A';
INSERT INTO #table SELECT 'Vjd', '20160315', 5, 'B';
INSERT INTO #table SELECT 'Viz', '20160315', 6, 'C';
INSERT INTO #table SELECT 'Hyd', '20160315', 4, 'A';
INSERT INTO #table SELECT 'Vjd', '20160515', 5, 'B';
INSERT INTO #table SELECT 'Viz', '20160515', 6, 'C';
SELECT
loc,
COUNT(CASE WHEN YEAR([date]) = 2016 AND MONTH([date]) = 1 AND sts = 'A' THEN 1 END) AS Jan_A,
COUNT(CASE WHEN YEAR([date]) = 2016 AND MONTH([date]) = 1 AND sts = 'B' THEN 1 END) AS Jan_B,
COUNT(CASE WHEN YEAR([date]) = 2016 AND MONTH([date]) = 1 AND sts = 'C' THEN 1 END) AS Jan_C,
COUNT(CASE WHEN YEAR([date]) = 2016 AND MONTH([date]) = 3 AND sts = 'A' THEN 1 END) AS Mar_A,
COUNT(CASE WHEN YEAR([date]) = 2016 AND MONTH([date]) = 3 AND sts = 'B' THEN 1 END) AS Mar_B,
COUNT(CASE WHEN YEAR([date]) = 2016 AND MONTH([date]) = 3 AND sts = 'C' THEN 1 END) AS Mar_C,
COUNT(CASE WHEN YEAR([date]) = 2016 AND MONTH([date]) = 5 AND sts = 'A' THEN 1 END) AS May_A,
COUNT(CASE WHEN YEAR([date]) = 2016 AND MONTH([date]) = 5 AND sts = 'B' THEN 1 END) AS May_B,
COUNT(CASE WHEN YEAR([date]) = 2016 AND MONTH([date]) = 5 AND sts = 'C' THEN 1 END) AS May_C
FROM
#table
GROUP BY
loc;
Results:
loc Jan_A Jan_B Jan_C Mar_A Mar_B Mar_C May_A May_B May_C
Hyd 1 0 0 2 0 0 0 0 0
Viz 0 0 1 0 0 1 0 0 1
Vjd 0 1 0 0 1 0 0 1 0

SQL Query to COUNT fields that match a certain value across all rows in a table

I am trying (and failing) to craft a simple SQL query (for SQL Server 2012) that counts the number of occurrences of a value for a given date range.
This is a collection of results from a survey.
So the end result would show there are only 3 lots of values matching '2' and
6 values matching '1'.
Even better if the final result could return 3 values:
MatchZero = 62
MatchOne = 6
MatchTwo = 3
Something Like (I know this is horribly out):
SELECT
COUNT(0) AS MatchZero,
COUNT(1) AS MatchOne,
COUNT(2) As MatchTwo
WHERE dated BETWEEN '2014-01-01' AND '2014-02-01'
I don't need it grouped by date or anything, simply a total value for each.
Any insights would be greatly received.
+------------+----------+--------------+-------------+------+-----------+------------+
| QuestionId | friendly | professional | comfortable | rate | recommend | dated |
+------------+----------+--------------+-------------+------+-----------+------------+
| 3 | 0 | 0 | 0 | 0 | 0 | 2014-02-12 |
| 9 | 0 | 0 | 0 | 0 | 0 | 2014-02-12 |
| 14 | 0 | 0 | 0 | 2 | 0 | 2014-02-13 |
| 15 | 0 | 0 | 0 | 0 | 0 | 2014-01-06 |
| 19 | 0 | 1 | 2 | 0 | 0 | 2014-01-01 |
| 20 | 0 | 0 | 0 | 0 | 0 | 2013-12-01 |
| 21 | 0 | 1 | 0 | 0 | 0 | 2014-01-01 |
| 22 | 0 | 1 | 0 | 0 | 0 | 2014-01-01 |
| 23 | 0 | 0 | 0 | 0 | 0 | 2014-01-24 |
| 27 | 0 | 0 | 0 | 0 | 0 | 2014-01-31 |
| 30 | 0 | 1 | 2 | 0 | 0 | 2014-01-27 |
| 31 | 0 | 0 | 0 | 0 | 0 | 2014-01-11 |
| 36 | 0 | 0 | 0 | 1 | 1 | 2014-01-22 |
+------------+----------+--------------+-------------+------+-----------+------------+
You can use conditional aggregation:
SELECT SUM((CASE WHEN friendly = 0 THEN 1 ELSE 0 END) +
(CASE WHEN professional = 0 THEN 1 ELSE 0 END) +
(CASE WHEN comfortable = 0 THEN 1 ELSE 0 END) +
(CASE WHEN rate = 0 THEN 1 ELSE 0 END) +
(CASE WHEN recommend = 0 THEN 1 ELSE 0 END) +
) AS MatchZero,
SUM((CASE WHEN friendly = 1 THEN 1 ELSE 0 END) +
(CASE WHEN professional = 1 THEN 1 ELSE 0 END) +
(CASE WHEN comfortable = 1 THEN 1 ELSE 0 END) +
(CASE WHEN rate = 1 THEN 1 ELSE 0 END) +
(CASE WHEN recommend = 1 THEN 1 ELSE 0 END) +
) AS MatchOne,
SUM((CASE WHEN friendly = 2 THEN 1 ELSE 0 END) +
(CASE WHEN professional = 2 THEN 1 ELSE 0 END) +
(CASE WHEN comfortable = 2 THEN 1 ELSE 0 END) +
(CASE WHEN rate = 2 THEN 1 ELSE 0 END) +
(CASE WHEN recommend = 2 THEN 1 ELSE 0 END) +
) AS MatchTwo
FROM . . .
WHERE dated BETWEEN '2014-01-01' AND '2014-02-01';
If I understand you correctly, you want to count the zeros, ones and twos for a particular (or each) column in your table. If this is correct, then you could do something like this:
select sum(case when your_column = 0 then 1 else 0 end) as zeros
, sum(case when your_column = 1 then 1 else 0 end) as ones
--- and so on
from your_table
-- where conditions go here
If you want to count the total for more than one column, enclose the needed case...ends in the sum():
sum(
(case when column1 = 0 then 1 else 0 end) +
(case when column2 = 0 then 1 else 0 end)
-- and so on
) as zeros
Going with a simple unpivot you can get the desired result with less coding.
By simply changing the date range the correct count of each question type is counted.
SELECT
RANKING, COUNT(*) AS CNT
FROM
(SELECT
friendly,professional,comfortable,rate,recommend
FROM
your_table
WHERE
dated >= '1/1/1900' AND dated <= '1/1/2015'
) AS U UNPIVOT
(RANKING FOR QUESTION IN (friendly,professional,comfortable,rate,recommend)) AS UNP
GROUP BY
RANKING

Select and group by Year, Month and Condition

I have a table like this (this is really an example only):
+-------------+---------------------+---------------------+
| status | open_date | close_date |
+-------------+---------------------+---------------------+
| closed | 01-11-2014 19:32:44 | 01-11-2014 20:32:44 |
| open | 01-12-2014 22:33:49 | 02-12-2014 22:33:49 |
| open | 01-23-2014 22:08:24 | 03-23-2014 22:08:24 |
| closed | 02-01-2014 22:33:57 | 03-01-2014 22:33:57 |
| open | 02-01-2013 22:37:34 | 02-01-2013 23:37:34 |
| closed | 04-20-2013 15:23:00 | 05-20-2013 15:23:00 |
| open | 04-20-2013 12:21:49 | 05-20-2013 12:21:49 |
| closed | 04-25-2013 11:22:00 | 06-25-2013 11:22:00 |
| closed | 05-20-2013 14:23:49 | 10-20-2013 14:23:49 |
| closed | 04-20-2013 16:33:49 | 04-25-2013 16:33:49 |
+-------------+---------------------+---------------------*
And want to list all opened and closed cases by Year and Month, like this:
+-------------+---------------+--------------+
| Year | Month | Opened Cases | Closed Cases |
+-------------+---------------+--------------+
| 2014 | 4 | 10 | 5 |
| 2014 | 3 | 9 | 7 |
| 2014 | 2 | 15 | 10 |
| 2014 | 1 | 12 | 1 |
| 2013 | 12 | 30 | 9 |
| 2013 | 11 | 5 | 50 |
+--------------+--------------+--------------+
I have a select like this:
SELECT
YEAR(open_date) AS TheYear,
MONTH(open_date) AS TheMonth,
sum(CASE WHEN open_date = ??? THEN 1 ELSE 0 END) TheOpened
sum(CASE WHEN close_date = ??? THEN 1 ELSE 0 END) TheClosed
FROM
TABLE
WHERE
CASEGROUP= 'SUPPORT'
GROUP BY
MONTH(open_date),
YEAR(open_date)
ORDER BY
TheYear DESC,
TheMonth ASC
Try this
SELECT
YEAR(open_date) AS TheYear,
MONTH(open_date) AS TheMonth,
sum(CASE WHEN open_status= 'Closed' THEN 0 ELSE 1 END) TheOpened,
sum(CASE WHEN open_status= 'Closed' THEN 1 ELSE 0 END) TheClosed
FROM
TABLE
WHERE
CASEGROUP= 'SUPPORT'
GROUP BY
MONTH(open_date),
YEAR(open_date)
ORDER BY
TheYear DESC,
TheMonth ASC
select [Year], [Month], Sum([Opened Cases]), sum([Closed Cases]) from (
select year(open_date) as [Year], MONTH(open_date) as [Month], count(*) as [Opened Cases] ,0 as [Closed Cases]
from [table] where status='open'
group by year(open_date), MONTH(open_date)
union
select year(close_date), MONTH(close_date), 0,count(*)
from [table] where status='closed'
group by year(close_date), MONTH(close_date)) as o
group by [Year], [Month]
Found it.
SELECT
YEAR(open_time) AS TheYear,
MONTH(open_time) AS TheMonth,
sum(CASE WHEN DATEPART(YYYY, open_time)= YEAR(open_time) AND DATEPART(MM, open_time)= MONTH(open_time) THEN 1 ELSE 0 END) TheOpened,
sum(CASE WHEN status = 'closed' THEN 1 ELSE 0 END) TheClosed
FROM
TABLE
WHERE
CASEGROUP= 'SUPPORT'
GROUP BY
MONTH(open_date),
YEAR(open_date)
ORDER BY
TheYear DESC,
TheMonth ASC