Balance in SQL Server query by month by account - sql-server

I need to build a query to get all the account's monthly balances between Jan/2020 and Dec/2020.
Basically I need this:
Account_id| Year | Jan |Feb| Mar| Apr|May | Jun| Jul| Aug|Sep| Oct| Nov|Dec
--------- ---- --- --- --- --- --- --- --- --- --- --- --- ---
1 | 2020 | 200 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |-500| 400| 0
2 | 2020 | 0 | 0 | 0 | 500| 0 | 0 | 900| 0 | 0 | 100| 0 | 0
3 | 2020 | 100 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 200| 500| 0
Sample data:
Table Accounts:
account_id| customer_id|.....
--------- ---- --- --- --
1 | x1 |......
2 | x2 |.....
Table Transfer_ins:
id | account_id|amount
--------- ---- --- -
xx | 1 | 100
xx | 2 | 300
Table Transfer_outs:
id | account_id|amount
--------- ---- --- --
xx | 1 | 100
xx | 2 | 300
Table Transfer_ins:
id | account_id| amount|
--------- ---- --- --- --
yy | 1 | 100 |
yy | 2 | 300 |
Table d_month:
id| month_id|action_month|
--------- ---- --- --- --
x1| 1 | january |
x4 2 | february |
Table pix_movements:
id |account_id| in_or_out |pix_amount
--------- ---- --- --- -- ----
yy | 1 | pix_out | 300
yy | 2 | pix_in | 900
Table d_time:
time_id|action_stamp | week_id | month_id |year_id
--------- ---- --- --- -- ------------------------
uu |2020-01-04T15:00:55.960Z| zz | yy | xx
uu |2020-01-04T15:00:55.960Z| zz | yy | xx
This is what I wrote:
SELECT
account_id, action_month,
ISNULL(SUM(CASE WHEN month(action_month) = 1 THEN transfer_ins.amount END)+SUM(CASE WHEN month(action_month) = 1 AND pix_movements.in_or_out = "pix_in" THEN pix.movements.amount END)-SUM(CASE WHEN month(action_month) = 1 THEN transfer_outs.amount END)-SUM(CASE WHEN month(action_month) = 1 AND pix_movements.in_or_out = "pix_out" THEN pix.movements.amount END), 0) Jan
ISNULL(SUM(CASE WHEN month(action_month) = 2 THEN transfer_ins.amount END)+SUM(CASE WHEN month(action_month) = 2 AND pix_movements.in_or_out = "pix_in" THEN pix.movements.amount END)-SUM(CASE WHEN month(action_month) = 2 THEN transfer_outs.amount END)-SUM(CASE WHEN month(action_month) = 2 AND pix_movements.in_or_out = "pix_out" THEN pix.movements.amount END), 0) Feb
ISNULL(SUM(CASE WHEN month(action_month) = 3 THEN transfer_ins.amount END)+SUM(CASE WHEN month(action_month) = 3 AND pix_movements.in_or_out = "pix_in" THEN pix.movements.amount END)-SUM(CASE WHEN month(action_month) = 3 THEN transfer_outs.amount END)-SUM(CASE WHEN month(action_month) = 3 AND pix_movements.in_or_out = "pix_out" THEN pix.movements.amount END), 0) Mar
ISNULL(SUM(CASE WHEN month(action_month) = 4 THEN transfer_ins.amount END)+SUM(CASE WHEN month(action_month) = 4 AND pix_movements.in_or_out = "pix_in" THEN pix.movements.amount END)-SUM(CASE WHEN month(action_month) = 4 THEN transfer_outs.amount END)-SUM(CASE WHEN month(action_month) = 4 AND pix_movements.in_or_out = "pix_out" THEN pix.movements.amount END), 0) Apr
ISNULL(SUM(CASE WHEN month(action_month) = 5 THEN transfer_ins.amount END)+SUM(CASE WHEN month(action_month) = 5 AND pix_movements.in_or_out = "pix_in" THEN pix.movements.amount END)-SUM(CASE WHEN month(action_month) = 5 THEN transfer_outs.amount END)-SUM(CASE WHEN month(action_month) = 5 AND pix_movements.in_or_out = "pix_out" THEN pix.movements.amount END), 0) May
ISNULL(SUM(CASE WHEN month(action_month) = 6 THEN transfer_ins.amount END)+SUM(CASE WHEN month(action_month) = 6 AND pix_movements.in_or_out = "pix_in" THEN pix.movements.amount END)-SUM(CASE WHEN month(action_month) = 6 THEN transfer_outs.amount END)-SUM(CASE WHEN month(action_month) = 6 AND pix_movements.in_or_out = "pix_out" THEN pix.movements.amount END), 0) Jun
ISNULL(SUM(CASE WHEN month(action_month) = 7 THEN transfer_ins.amount END)+SUM(CASE WHEN month(action_month) = 7 AND pix_movements.in_or_out = "pix_in" THEN pix.movements.amount END)-SUM(CASE WHEN month(action_month) = 7 THEN transfer_outs.amount END)-SUM(CASE WHEN month(action_month) = 7 AND pix_movements.in_or_out = "pix_out" THEN pix.movements.amount END), 0) Jul
ISNULL(SUM(CASE WHEN month(action_month) = 8 THEN transfer_ins.amount END)+SUM(CASE WHEN month(action_month) = 8 AND pix_movements.in_or_out = "pix_in" THEN pix.movements.amount END)-SUM(CASE WHEN month(action_month) = 8 THEN transfer_outs.amount END)-SUM(CASE WHEN month(action_month) = 8 AND pix_movements.in_or_out = "pix_out" THEN pix.movements.amount END), 0) Aug
ISNULL(SUM(CASE WHEN month(action_month) = 9 THEN transfer_ins.amount END)+SUM(CASE WHEN month(action_month) = 9 AND pix_movements.in_or_out = "pix_in" THEN pix.movements.amount END)-SUM(CASE WHEN month(action_month) = 9 THEN transfer_outs.amount END)-SUM(CASE WHEN month(action_month) = 9 AND pix_movements.in_or_out = "pix_out" THEN pix.movements.amount END), 0) Sep
ISNULL(SUM(CASE WHEN month(action_month) = 10 THEN transfer_ins.amount END)+SUM(CASE WHEN month(action_month) = 10 AND pix_movements.in_or_out = "pix_in" THEN pix.movements.amount END)-SUM(CASE WHEN month(action_month) = 10 THEN transfer_outs.amount END)-SUM(CASE WHEN month(action_month) = 10 AND pix_movements.in_or_out = "pix_out" THEN pix.movements.amount END), 0) Oct
ISNULL(SUM(CASE WHEN month(action_month) = 11 THEN transfer_ins.amount END)+SUM(CASE WHEN month(action_month) = 11 AND pix_movements.in_or_out = "pix_in" THEN pix.movements.amount END)-SUM(CASE WHEN month(action_month) = 11 THEN transfer_outs.amount END)-SUM(CASE WHEN month(action_month) = 11 AND pix_movements.in_or_out = "pix_out" THEN pix.movements.amount END), 0) Nov
ISNULL(SUM(CASE WHEN month(action_month) = 11 THEN transfer_ins.amount END)+SUM(CASE WHEN month(action_month) = 12 AND pix_movements.in_or_out = "pix_in" THEN pix.movements.amount END)-SUM(CASE WHEN month(action_month) = 12 THEN transfer_outs.amount END)-SUM(CASE WHEN month(action_month) = 12 AND pix_movements.in_or_out = "pix_out" THEN pix.movements.amount END), 0) Dic
FROM
accounts
INNER JOIN
pix_movemets ON accounts.account_id = pix_movements.account_id
INNER JOIN
transfer_outs ON accounts.account_id = transfer_outs.account_id
INNER JOIN
transfer_ins ON accounts.account_id = transfer_ins.account_id
GROUP BY
account_id
But I keep getting errors, I don't know how to do it.
I understand that I need to SUM the amount of the transfer_ins.amount + pix_movements.pix_amount where = pix_movements.in_or_out = "in". The result of each month I need to subtract with transfer_outs.amount + pix_movements.pix_amount where = pix.movements.in_or_out = "out" by account.
The tables are in the image below. I think that I need to use the tables: transfer_ins transfer_outs accounts pix_movements d_time d_year
Schema-Entity:

Related

SQL Server Group By Combine Pivot Table Approaches

I have tables which designed like survey questions.
Answer table store like below. One answer related with three questions. QuestionId 1 and QuestionId 2 store Yes or No answers. If QuestionId 1 and QuestionId 2 both of them answer Yes, I want QuesiontId 3 to sum count with column value otherwise alias should be Others. Which approach is better , could u please help :)
AnswerId | QuestionId | QuestionOptionText
---------+------------+-------------------
1 | 1 | No
1 | 2 | No
1 | 3 | 0
--------------------------------------
2 | 1 | Yes
2 | 2 | No
2 | 3 | 0
--------------------------------------
3 | 1 | No
3 | 2 | Yes
3 | 3 | 1-10
--------------------------------------
4 | 1 | Yes
4 | 2 | Yes
4 | 3 | 1-10
--------------------------------------
5 | 1 | Yes
5 | 2 | Yes
5 | 3 | 11-20
Result should be like that
1-10 | 11-20 | Other
-----+-------+-------
1 | 1 | 3
I think you need a self join of the three types of question, and then the summing logic is easier. A different table structure would probably have simplified things. Normally you would have each question in a separate column.
select
sum(iif(ans1 = 'Yes' and ans2 = 'Yes' and ans3 = '1-10',1,0)) as '1-10',
sum(iif(ans1 = 'Yes' and ans2 = 'Yes' and ans3 = '11-20',1,0)) as '11-20',
sum(iif(ans1 <> 'Yes' or ans2 = 'Yes',1,0)) as 'other'
from (
select QuestionOptionText as ans1 from t where QuestionId = 1
) as a1
inner join (
select QuestionOptionText as ans2 from t where QuestionId = 2
) as a2
on a1.AnswerId = a2.AnswerId
inner join (
select QuestionOptionText as ans3 from t where QuestionId = 3
) as a3
on a1.AnswerId = a3.AnswerId
Is this what you want?
select sum(case when QuestionOptionText = '1-10' then 1 else 0 end),
sum(case when QuestionOptionText = '11-20' then 1 else 0 end),
sum(case when QuestionOptionText not in ('1-10', '11-20') then 1 else 0 end)
from t
where QuestionId = 3;
You could do this with two levels of aggregation. First compute the outcome of each series of answerId, the pivot the resultset:
select
sum(case when res = '1-10' then 1 else 0 end) res_1_10,
sum(case when res = '11-20' then 1 else 0 end) res_1_20,
sum(case when res = 'Other' then 1 else 0 end) res_other
from (
select
case when max(case when QuestionId in (1, 2) then QuestionOptionText end) = 'Yes'
then max(case when QuestionId = 3 then QuestionOptionText end)
else 'Other'
end res
from mytable
group by answerId
) t

SQL Server tabulating survey data for every month

I have a survey table with many columns but i am focusing on these 2, survey_date and over_rating. i am not sure if it is possible to be done in a single query. I am using sql server 2012. This is my sample data.
select survey_date, overall_rating from survey
survey_date overall_rating
2017-01-06 15:09:51.940 6
2017-02-06 14:18:18.620 4
2017-05-07 16:03:12.037 7
2017-05-23 10:41:30.357 7
2017-05-23 10:41:30.357 5
2017-05-24 12:05:25.217 8
2017-06-01 09:03:47.727 7
2017-06-05 09:01:07.283 9
2017-06-05 09:28:12.597 6
2017-06-15 09:47:29.407 7
2017-07-06 12:10:50.003 2
2017-07-06 13:45:52.997 7
2017-08-06 14:00:35.403 5
2017-08-09 12:21:17.367 8
I need to count the occurrence for each rating 1-10, for each month, and sum it up. Example June 15, rating 10 have 1, rating 9 have 10, ...
This is the result table:
Month 10 9 8 7 6 5 4 3 2 1 Avg Score Total Total >=6 CSI
June'15 1 10 20 3 0 0 0 0 0 0 8 34 34 100%
July'15 1 16 14 0 0 0 0 0 1 0 9 32 31 99%
August'15 7 6 6 0 0 0 0 0 0 0 9 19 19 100%
September'15 0 2 2 0 0 0 0 0 0 0 9 4 4 100%
November'15 0 1 2 0 0 0 0 0 0 0 8 3 3 100%
December'15 0 7 3 4 2 0 0 0 0 0 8 16 16 100%
i have tried this query but is partly wrong as there is duplicate month for each rating:
select si.yr, si.mn,
case when si.overall_rating = 10 then count(si.overall_rating) else 0 end as '10',
case when si.overall_rating = 9 then count(si.overall_rating) else 0 end as '9',
case when si.overall_rating = 8 then count(si.overall_rating) else 0 end as '8',
case when si.overall_rating = 7 then count(si.overall_rating) else 0 end as '7',
case when si.overall_rating = 6 then count(si.overall_rating) else 0 end as '6',
case when si.overall_rating = 5 then count(si.overall_rating) else 0 end as '5',
case when si.overall_rating = 4 then count(si.overall_rating) else 0 end as '4',
case when si.overall_rating = 3 then count(si.overall_rating) else 0 end as '3',
case when si.overall_rating = 2 then count(si.overall_rating) else 0 end as '2',
case when si.overall_rating = 1 then count(si.overall_rating) else 0 end as '1',
sum(si.overall_rating) as month_count
from
(select YEAR(s.survey_date) yr, MONTH(s.survey_date) mn, s.overall_rating
from survey s where s.status='Submitted' and s.survey_date >= '2017-01-01' AND s.survey_date <= '2017-12-31'
group by YEAR(s.survey_date), MONTH(s.survey_date), s.overall_rating) si group by si.yr, si.mn, si.overall_rating;
Results:
yr mm 10 9 8 7 6 5 4 3 2 1 total
2017 1 0 0 0 0 1 0 0 0 0 0 6
2017 2 0 0 0 0 0 0 1 0 0 0 4
2017 5 0 0 0 0 0 1 0 0 0 0 5
2017 5 0 0 0 1 0 0 0 0 0 0 7
2017 5 0 0 1 0 0 0 0 0 0 0 8
2017 6 0 0 0 0 1 0 0 0 0 0 6
2017 6 0 0 0 1 0 0 0 0 0 0 7
2017 6 0 1 0 0 0 0 0 0 0 0 9
2017 7 0 0 0 0 0 0 0 0 1 0 2
2017 7 0 0 0 1 0 0 0 0 0 0 7
2017 8 0 0 0 0 0 1 0 0 0 0 5
2017 8 0 0 1 0 0 0 0 0 0 0 8
As you can see 5 and 6 are repeated for different rating. If anyone could tell me is it possible to be done in a single query. Thanks
I think I understand what you are trying to achieve here and you'll be pleased to know you are not far off. You have the right idea in using a conditional aggregate, but you need to wrap your conditional case expression in the aggregate, not the other way around. To do a conditional count, you can simply return 1 for a condition match and 0 for a no match and then sum up the result.
Doing this allows your group by to remain nice and simple:
declare #t table(survey_date datetime,overall_rating int);
insert into #t values ('2017-01-06 15:09:51.940',6),('2017-02-06 14:18:18.620',4),('2017-05-07 16:03:12.037',7),('2017-05-23 10:41:30.357',7),('2017-05-23 10:41:30.357',5),('2017-05-24 12:05:25.217',8),('2017-06-01 09:03:47.727',7),('2017-06-05 09:01:07.283',9),('2017-06-05 09:28:12.597',6),('2017-06-15 09:47:29.407',7),('2017-07-06 12:10:50.003',2),('2017-07-06 13:45:52.997',7),('2017-08-06 14:00:35.403',5),('2017-08-09 12:21:17.367',8);
select dateadd(m,datediff(m,0,survey_date),0) as [Month]
,sum(case when overall_rating = 10 then 1 else 0 end) as [10]
,sum(case when overall_rating = 9 then 1 else 0 end) as [9]
,sum(case when overall_rating = 8 then 1 else 0 end) as [8]
,sum(case when overall_rating = 7 then 1 else 0 end) as [7]
,sum(case when overall_rating = 6 then 1 else 0 end) as [6]
,sum(case when overall_rating = 5 then 1 else 0 end) as [5]
,sum(case when overall_rating = 4 then 1 else 0 end) as [4]
,sum(case when overall_rating = 3 then 1 else 0 end) as [3]
,sum(case when overall_rating = 2 then 1 else 0 end) as [2]
,sum(case when overall_rating = 1 then 1 else 0 end) as [1]
,count(overall_rating) as ScoresReturned
,sum(overall_rating) as TotalScore
,avg(cast(overall_rating as decimal(10,0))) as Average
from #t
group by dateadd(m,datediff(m,0,survey_date),0)
order by [Month];
Output:
+-------------------------+----+---+---+---+---+---+---+---+---+---+----------------+------------+----------+
| Month | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | ScoresReturned | TotalScore | Average |
+-------------------------+----+---+---+---+---+---+---+---+---+---+----------------+------------+----------+
| 2017-01-01 00:00:00.000 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 6 | 6.000000 |
| 2017-02-01 00:00:00.000 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 4 | 4.000000 |
| 2017-05-01 00:00:00.000 | 0 | 0 | 1 | 2 | 0 | 1 | 0 | 0 | 0 | 0 | 4 | 27 | 6.750000 |
| 2017-06-01 00:00:00.000 | 0 | 1 | 0 | 2 | 1 | 0 | 0 | 0 | 0 | 0 | 4 | 29 | 7.250000 |
| 2017-07-01 00:00:00.000 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 2 | 9 | 4.500000 |
| 2017-08-01 00:00:00.000 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 2 | 13 | 6.500000 |
+-------------------------+----+---+---+---+---+---+---+---+---+---+----------------+------------+----------+
select si.yr, si.mn,
case when si.overall_rating = 10 then count(si.overall_rating) else 0 end as '10',
case when si.overall_rating = 9 then count(si.overall_rating) else 0 end as '9',
case when si.overall_rating = 8 then count(si.overall_rating) else 0 end as '8',
case when si.overall_rating = 7 then count(si.overall_rating) else 0 end as '7',
case when si.overall_rating = 6 then count(si.overall_rating) else 0 end as '6',
case when si.overall_rating = 5 then count(si.overall_rating) else 0 end as '5',
case when si.overall_rating = 4 then count(si.overall_rating) else 0 end as '4',
case when si.overall_rating = 3 then count(si.overall_rating) else 0 end as '3',
case when si.overall_rating = 2 then count(si.overall_rating) else 0 end as '2',
case when si.overall_rating = 1 then count(si.overall_rating) else 0 end as '1',
sum(si.overall_rating) as month_count
from
(select YEAR(s.survey_date) yr, MONTH(s.survey_date) mn, s.overall_rating
from survey s where s.status='Submitted' and s.survey_date >= '2017-01-01' AND s.survey_date <= '2017-12-31'
group by YEAR(s.survey_date), MONTH(s.survey_date), s.overall_rating) si group by si.yr, si.mn;
You must remove si.overall_rating in Group By
Oh! I posted late, anyway you can try this otherwise.
DATA:
IF ( OBJECT_ID('tempdb..#temptable') IS NOT NULL )
BEGIN
DROP TABLE #temptable
END
CREATE TABLE #temptable
(
survey_date DATETIME ,
overall_rating NUMERIC(22,2)
)
INSERT INTO #temptable
( survey_date, overall_rating )
VALUES ( '2017-01-06 15:09:51.940', 6 ),
( '2017-02-06 14:18:18.620', 4 ),
( '2017-05-07 16:03:12.037', 7 ),
( '2017-05-23 10:41:30.357', 7 ),
( '2017-05-23 10:41:30.357', 5 ),
( '2017-05-24 12:05:25.217', 8 ),
( '2017-06-01 09:03:47.727', 7 ),
( '2017-06-05 09:01:07.283', 9 ),
( '2017-06-05 09:28:12.597', 6 ),
( '2017-06-15 09:47:29.407', 7 ),
( '2017-07-06 12:10:50.003', 2 ),
( '2017-07-06 13:45:52.997', 7 ),
( '2017-08-06 14:00:35.403', 5 ),
( '2017-08-09 12:21:17.367', 8 )
QUERY:
;
WITH CTE
AS ( SELECT DATENAME(month, survey_date) + ' '''
+ RIGHT(CAST(YEAR(survey_date) AS NVARCHAR(4)),
2) AS [Month] ,
ISNULL([1], 0) [1] ,
ISNULL([2], 0) [2] ,
ISNULL([3], 0) [3] ,
ISNULL([4], 0) [4] ,
ISNULL([5], 0) [5] ,
ISNULL([6], 0) [6] ,
ISNULL([7], 0) [7] ,
ISNULL([8], 0) [8] ,
ISNULL([9], 0) [9] ,
ISNULL([10], 0) [10],
Total,
Average
FROM ( SELECT survey_date ,
COUNT(overall_rating) overall_rating,
CAST(SUM(overall_rating) AS INT) Total,
AVG(overall_rating) Average
FROM ( SELECT DATEADD(MONTH,
DATEDIFF(MONTH,
0, survey_date),
0) survey_date ,
overall_rating
FROM #temptable
) T
GROUP BY t.survey_date
) PVT PIVOT ( SUM(overall_rating) FOR overall_rating IN ( [1],
[2], [3], [4],
[5], [6], [7],
[8], [9], [10] ) ) P
)
SELECT [Month] ,
ISNULL([1], 0) [1] ,
ISNULL([2], 0) [2] ,
ISNULL([3], 0) [3] ,
ISNULL([4], 0) [4] ,
ISNULL([5], 0) [5] ,
ISNULL([6], 0) [6] ,
ISNULL([7], 0) [7] ,
ISNULL([8], 0) [8] ,
ISNULL([9], 0) [9] ,
ISNULL([10], 0) [10],
Total,
Average
FROM CTE
RESULT:
Month 1 2 3 4 5 6 7 8 9 10 Total Average
----------------------- ------ ---- ----- ----- ----- ----- ---- ---- ----- ----- ----------- -------------
January '17 1 0 0 0 0 0 0 0 0 0 6 6.000000
February '17 1 0 0 0 0 0 0 0 0 0 4 4.000000
May '17 0 0 0 4 0 0 0 0 0 0 27 6.750000
June '17 0 0 0 4 0 0 0 0 0 0 29 7.250000
July '17 0 2 0 0 0 0 0 0 0 0 9 4.500000
August '17 0 2 0 0 0 0 0 0 0 0 13 6.500000
(6 row(s) affected)

MSSQL count number of items based on time differences

I have a table (tbl_results) of information like so:
name | time_in_minutes
-------------
jonny | 14
jonny | 27
jonny | 28
jonny | 56
jonny | 57
jonny | 58
sarah | 12
sarah | 16
sarah | 17
sarah | 24
sarah | 25
and i would love to know how to write a query (cross join maybe?), that sums up the number of times within a certain time period. For the example above I would use timings of 10 minutes. So the following would be the result.
name | 0-10 | 11-20 | 21-30 | 31-40 | 41-50 | 51-60
jonny | 0 | 1 | 2 | 0 | 0 | 3
sarah | 0 | 3 | 2 | 0 | 0 | 0
I would write some code, but I am really not even sure where to start with a query like this.
Using conditional aggregation:
SELECT
name,
[0-10] = COUNT(CASE WHEN time_in_minutes BETWEEN 0 AND 10 THEN 1 END),
[11-20] = COUNT(CASE WHEN time_in_minutes BETWEEN 0 AND 10 THEN 1 END),
[21-30] = COUNT(CASE WHEN time_in_minutes BETWEEN 0 AND 10 THEN 1 END),
[31-40] = COUNT(CASE WHEN time_in_minutes BETWEEN 0 AND 10 THEN 1 END),
[41-50] = COUNT(CASE WHEN time_in_minutes BETWEEN 0 AND 10 THEN 1 END),
[51-60] = COUNT(CASE WHEN time_in_minutes BETWEEN 0 AND 10 THEN 1 END)
FROM tbl
GROUP BY name

Grouping SQL columns from one table

I am currently having difficulty getting the correct values from my table. Here is my table
NOTE: The column Status has 3 possible values (Cleaned, Unclean, Closed)
+-----------+-------------+--------+------------+
|ApplicantID|ApplicantName| Status | HireDate |
+-----------+-------------+--------+------------+
| 1 | John Smith |Cleaned |08/26/2015 |
| 2 | Alex Murphy |Closed |09/12/2015 |
| 3 | Oliver David|Cleaned |01/11/2015 |
| 4 | Max Payne |Unclean |03/18/2015 |
+-----------+-------------+--------+------------+
The output I'm expecting and it should also be sorted by year.
For example I call all these records for the year 2015 which I get using the variable #Year.
NOTE: The column Total is the SUM of Cleaned and Unclean
+---------+-----------+-----------+----------+---------+
| Month | Cleaned | Unclean | Closed | Total |
+---------+-----------+-----------+----------+---------+
| January| 1 | 0 | 0 | 1 |
| February| 0 | 0 | 0 | 0 |
| March | 0 | 1 | 0 | 1 |
| April | 0 | 0 | 0 | 0 |
| May | 0 | 0 | 0 | 0 |
| June | 0 | 0 | 0 | 0 |
| July | 0 | 0 | 0 | 0 |
| August | 1 | 0 | 0 | 1 |
|September| 0 | 0 | 1 | 0 |
| October| 0 | 0 | 0 | 0 |
| November| 0 | 0 | 0 | 0 |
| December| 0 | 0 | 0 | 0 |
+---------+-----------+-----------+----------+---------+
I can't seem to get the right code, for the sql this is my current code.
SELECT Month(HireDate) AS Month, COUNT(*)
FROM Hires
GROUP BY Month(HireDate)
I know my coding is wrong, because it is incomplete.
Generate a list of numbers from 1 to 12 first to hold all months. Then do a LEFT JOIN on Hires to make sure all missing months are accounted for. Then use conditional aggregation for the totals:
SQL Fiddle
;WITH CteMonths AS(
SELECT * FROM(VALUES
(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)
)t(N)
)
SELECT
Month = DATENAME(MONTH, DATEADD(MONTH, N-1,0)),
Cleaned = SUM(CASE WHEN h.Status = 'Cleaned' THEN 1 ELSE 0 END),
Closed = SUM(CASE WHEN h.Status = 'Closed' THEN 1 ELSE 0 END),
Unclean = SUM(CASE WHEN h.Status = 'Unclean' THEN 1 ELSE 0 END),
Total = SUM(CASE WHEN h.Status IN('Cleaned', 'Unclean') THEN 1 ELSE 0 END)
FROM CteMonths m
LEFT JOIN Hires h
ON m.N = MONTH(h.HireDate)
--AND YEAR(h.HireDate) = #year --uncomment this line to filter for year.
GROUP BY m.N
ORDER BY m.N
If you want to include the YEAR:
SQL Fiddle
;WITH CteMonths AS(
SELECT * FROM(VALUES
(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)
)t(N)
),
CteYears(yr) AS(
SELECT DISTINCT YEAR(HireDate) FROM Hires
),
CteAllDates(dt) AS(
SELECT
DATEADD(MONTH, m.N - 1, DATEADD(YEAR, y.yr - 1900, 0))
FROM CteMonths m
CROSS JOIN CteYears y
)
SELECT
Year = YEAR(d.dt),
Month = DATENAME(MONTH, d.dt),
Cleaned = SUM(CASE WHEN h.Status = 'Cleaned' THEN 1 ELSE 0 END),
Closed = SUM(CASE WHEN h.Status = 'Closed' THEN 1 ELSE 0 END),
Unclean = SUM(CASE WHEN h.Status = 'Unclean' THEN 1 ELSE 0 END),
Total = SUM(CASE WHEN h.Status IN('Cleaned', 'Unclean') THEN 1 ELSE 0 END)
FROM CteAllDates d
LEFT JOIN Hires h
ON MONTH(d.dt) = MONTH(h.HireDate)
AND YEAR(d.dt) = YEAR(h.HireDate)
GROUP BY YEAR(d.dt), MONTH(d.dt), DATENAME(MONTH, d.dt)
ORDER BY YEAR(d.dt), MONTH(d.dt)
If you want to filter for year, say #year = 2015, you can replace the previous ctes with:
;WITH CteMonths AS(
SELECT * FROM(VALUES
(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)
)t(N)
),
CteAllDates(dt) AS(
SELECT
DATEADD(MONTH, m.N - 1, DATEADD(YEAR, #year - 1900, 0))
FROM CteMonths m
)...
I suggest to create TEMP table with values from 1 to 12 (numbers of months) and JOIN your table with TEMP table. To achieve values as columns names you can use PIVOT or CASE. You can do It in following:
INSERT INTO #Months VALUES
(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)
SELECT DATENAME(MONTH, DATEADD(MONTH, m.Id-1, 0)) AS [Month]
, SUM(CASE WHEN [Status] = 'Cleaned' THEN 1 ELSE 0 END) AS [Cleaned]
, SUM(CASE WHEN [Status] = 'Closed' THEN 1 ELSE 0 END ) AS [Closed]
, SUM(CASE WHEN [Status] = 'Unclean' THEN 1 ELSE 0 END) AS [Unclean]
, SUM(CASE WHEN [Status] IN ('Unclean', 'Cleaned') THEN 1 ELSE 0 END) AS [Total]
FROM #Test t
RIGHT JOIN #Months m ON m.Id = MONTH(t.HireDate)
GROUP BY m.Id
OUTPUT
+---------+-----------+-----------+----------+---------+
| Month | Cleaned | Unclean | Closed | Total |
+---------+-----------+-----------+----------+---------+
| January | 1 | 0 | 0 | 1 |
| February| 0 | 0 | 0 | 0 |
| March | 0 | 1 | 0 | 1 |
| April | 0 | 0 | 0 | 0 |
| May | 0 | 0 | 0 | 0 |
| June | 0 | 0 | 0 | 0 |
| July | 0 | 0 | 0 | 0 |
| August | 1 | 0 | 0 | 1 |
|September| 0 | 0 | 1 | 0 |
| October | 0 | 0 | 0 | 0 |
| November| 0 | 0 | 0 | 0 |
| December| 0 | 0 | 0 | 0 |
+---------+-----------+-----------+----------+---------+
DEMO
You can test It at: SQL FIDDLE

Insert Query in SQL Server

I have this table TAB
ID | Trans
------------
1 | 99
2 | 99
3 | 99
2 | 90
4 | 22
4 | 22
2 | 99
2 | 90
I want to get the count of trans that appear together for a single id, for eg, '1 has 90 & 99' and '2 has 90 & 99' in the entire table so the count is 2. This is similar to Apriori Algorithm's Third Step.
I tried this but didn't work-
select
count(trans)
from
Tab
where
trans = 99 & 90
group by
ID
having
ID = 2
My expected ans for Trans- 90 & 99 is
Trans1 | Trans2 | Support
------------
90 | 99 | 1
I also want to insert this into a new table.
If I understood your problem correctly, you can use SUM(CASE WHEN...END) for this:
DECLARE
#trans1 INT = 99,
#trans2 INT = 90
SELECT
ID,
PairCount =
CASE
WHEN SUM(CASE WHEN Trans = #trans1 THEN 1 ELSE 0 END) >= SUM(CASE WHEN Trans = #trans2 THEN 1 ELSE 0 END)
THEN SUM(CASE WHEN Trans = #trans2 THEN 1 ELSE 0 END)
ELSE SUM(CASE WHEN Trans = #trans1 THEN 1 ELSE 0 END)
END,
Trans1 = SUM(CASE WHEN Trans = #trans1 THEN 1 ELSE 0 END),
Trans2 = SUM(CASE WHEN Trans = #trans2 THEN 1 ELSE 0 END)
FROM DS
WHERE Trans IN (#trans1, #trans2)
GROUP BY ID
RESULT
ID PairCount Trans1 Trans2
----------- ----------- ----------- -----------
1 0 1 0
2 2 2 2
3 0 1 0

Resources