How to get recent data and previous data in SQL - sql

If we have the following data, I want to get the data using the "SomeID" column or The "ApplicationID". So the data returned is basically the Amount in separate columns based on the "SomeID"
ID SomeID ApplicationID Amount
19 8 19 45.18
20 8 20 45.18
21 8 21 225.91
22 8 22 203.32
72 10 19 45.18
73 10 20 45.18
74 10 21 225.91
75 10 22 203.32
I want to return
Last Month repayment This Month repaymnrt Variance
45.18 45.18 0
45.18 45.18 0
225.91 225.91 0
203.32 203.32 0

I think you can do what you want using pivot or conditional aggregatoin:
select applicationId,
sum(case when someId = 8 then Amount else 0 end) as LastMonth,
sum(case when someId = 10 then Amount else 0 end) as ThisMonth,
sum(case when someId = 8 then -Amount
when someId = 10 then Amount
else 0
end) as Diff
from t
group by applicationId;

Related

SQL Pivot and get column row data

I have tables and data as below. Trying to get the Manufacturer and the questions they answered by joining and pivot but able to. Added the expected output at the end but no luck. Any suggestions are appreciated.
tblManufacturer
MFRID
MFRNum
1
3M
2
GM
3
HD
4
GL
tblMFRQuestions
MFRQID
MFRQTEXT
21
ENTER PRICE??
22
WHAT IS TIME??
23
WHAT IS RANGE??
tbMFRQuestionAnswers
MFRID
MRFRQID
MFRANSWER
1
21
55
1
22
9AM
1
23
105KM
2
21
57
2
22
10PM
2
23
535KM
3
21
355
3
22
12AM
3
23
5105KM
Expected Output:
MFRID MFRNUM ENTER PRICE?? WHAT IS TIME?? WHAT IS RANGE??
1 3M 55 9AM 105KM
2 GM 57 10PM 535KM
3 HD 355 12AM 5105KM
You could try something like this
select m.*,
max(case when q.MFRQTEXT='ENTER PRICE??' then qa.MFRANSWER else null end) [ENTER PRICE??],
max(case when q.MFRQTEXT='WHAT IS TIME??' then qa.MFRANSWER else null end) [WHAT IS TIME??],
max(case when q.MFRQTEXT='WHAT IS RANGE??' then qa.MFRANSWER else null end) [WHAT IS RANGE??]
from tblManufacturer m
join tbMFRQuestionAnswers qa on m.MFRID=qa.MFRID
join tblMFRQuestions q on qa.MFRQID=q.MFRQID
group by m.MFRID, m.MFRNum
order by m.MFRID, m.MFRNum;

select count (distinct) returning incorrect count

I'm trying to run a code that will summarise a list of clients based on age categories. I have the client ID and their ages, and am using a CASE WHEN to group the ages into buckets, then trying to count the client ids in each of those buckets.
For info - the Assisted Date field is just the date on which the client was served and this is just included in my testing to keep the results small - so I'm just focusing on Feb 2019 services that aren't Assessments; and the SIR ID is the location at which the service was provided.
select distinct
CASE
when CD.Age between 0 and 5 then '0-5'
when CD.Age between 6 and 11 then '6-11'
when CD.Age between 12 and 14 then '12-14'
when CD.Age between 15 and 17 then '15-17'
when CD.Age between 18 and 24 then '18-24'
when CD.Age between 25 and 54 then '25-54'
when CD.Age between 55 and 64 then '55-64'
when CD.Age > 65 then '65+'
else 'Unknown'
END AS Age_Group,
count(distinct AP.Source_Individual_ID) as "Count"
from dm.Assistance_Provided AP, rpt.ClientsDemographics CD
where CD.Source_Individual_ID = AP.Source_Individual_ID
and AP.SIR_ID = '1909'
and AP.Service_Provided <> 'Assessment'
and year(AP.Assisted_Date) = '2019'
and month(AP.Assisted_Date) = 2
group by CD.Age
If I run the code excluding the count(distinct) I end up with 17 rows of data. The 17 clients are all aged between 18-24 so the Age-Group for all clients come back as 18-24. So the Case When appears to be operating correctly.
However, if I run the code with the count(distinct), I end up with 3 rows of data. the Age Group 18-24 is listed 3 times and the Count as 2, 4, and 5 respectively for the 3 lines. I definitely have 17 different IDs in the list, but for some reason this is being reduced to a total of 11 when I add the count(distinct).
I've also tried removing the distinct from the select i.e. so
select
CASE
when CD.Age between ....
If I do that I get 5 rows - still all with age group 18-24, but then with 2,4,5,4,2 respectively - so then back to my total of 17. But I'm not sure why I'm not just getting one line back : Age Group: 18-24; Count: 17
What am I doing wrong?
I suspect that you should actually be aggregating by Source_Individual, and then taking conditional counts everywhere:
SELECT
CD.Source_Individual_ID,
COUNT(CASE WHEN CD.Age BETWEEN 0 AND 5 THEN 1 END) AS [0-5],
COUNT(CASE WHEN CD.Age BETWEEN 6 AND 11 THEN 1 END) AS [6-11],
COUNT(CASE WHEN CD.Age BETWEEN 12 AND 14 THEN 1 END) AS [12-14],
COUNT(CASE WHEN CD.Age BETWEEN 15 AND 17 THEN 1 END) AS [15-17],
COUNT(CASE WHEN CD.Age BETWEEN 18 AND 24 THEN 1 END) AS [18-24],
COUNT(CASE WHEN CD.Age BETWEEN 25 AND 54 THEN 1 END) AS [25-54],
COUNT(CASE WHEN CD.Age BETWEEN 55 AND 64 THEN 1 END) AS [55-64]
COUNT(CASE WHEN CD.Age > 65 THEN 1 END) AS [65+],
COUNT(*) AS [Number of Clients Assisted]
FROM dm.Assistance_Provided AP
INNER JOIN rpt.ClientsDemographics CD
ON CD.Source_Individual_ID = AP.Source_Individual_ID
WHERE
AP.SIR_ID = '1909' AND
AP.Service_Provided <> 'Assessment' AND
YEAR(AP.Assisted_Date) = 2019 AND
MONTH(AP.Assisted_Date) = 2
GROUP BY
CD.Source_Individual_ID;
Note that I have rewritten your query to use explicit, modern, inner joins, rather than the implicit joins you were using.
You need to put your case statement in your group by. As it is, since you group by CD.Age it will write a single row for every distinct age. In other words if you have two rows with Age = 12 and one row with Age = 13 you'll get two rows, both with 12-14 as their age group, but with a count of 2 for the first and 1 for the second. To make it more confusing, if you only had one row each, then because both rows are the same and you have the distinct clause it would only return 1 row with a count of 1.
If you put your case statement into the group by, then it will group by each distinct Age_Group instead. i.e., it does the case transformation first, then groups by it.
So try:
select
CASE
when CD.Age between 0 and 5 then '0-5'
when CD.Age between 6 and 11 then '6-11'
when CD.Age between 12 and 14 then '12-14'
when CD.Age between 15 and 17 then '15-17'
when CD.Age between 18 and 24 then '18-24'
when CD.Age between 25 and 54 then '25-54'
when CD.Age between 55 and 64 then '55-64'
when CD.Age > 65 then '65+'
else 'Unknown'
END AS Age_Group,
count(distinct AP.Source_Individual_ID) as "Number of Clients Assisted"
from dm.Assistance_Provided AP, rpt.ClientsDemographics CD
where CD.Source_Individual_ID = AP.Source_Individual_ID
and AP.SIR_ID = '1909'
and AP.Service_Provided <> 'Assessment'
and year(AP.Assisted_Date) = '2019'
and month(AP.Assisted_Date) = 2
group by CASE
when CD.Age between 0 and 5 then '0-5'
when CD.Age between 6 and 11 then '6-11'
when CD.Age between 12 and 14 then '12-14'
when CD.Age between 15 and 17 then '15-17'
when CD.Age between 18 and 24 then '18-24'
when CD.Age between 25 and 54 then '25-54'
when CD.Age between 55 and 64 then '55-64'
when CD.Age > 65 then '65+'
else 'Unknown'
END

Summary with breakdown of dates by dayrange

Here is raw table I have list of ids with dates and counts. I need to pivot counts and break down date current date getdate() to date on the table broken out by 0-5 days , 10-15 ....
Type Date Volume
-------- ----- ------
primary mar 10,2019 1
Sub mar 8,2019 2
Pending mar 13,2019 3
XX mar 4,2019 5
What I want is, to show the result something like this:
TYPE 0-5 Days 5-10 Days 11-15 Days 16-20 Days 21-30 Days Total
primary 1 4 1 6 1 13
sub 3 5 5 7 0 20
pending 1 1 1 1 1 5
5 10 7 14 2 38
I assume you're looking for a conditional sum of the volumes that compares the date with the current date. And with a rollup.
Then something like this :
SELECT Type,
SUM(CASE WHEN DATEDIFF(day,[Date],GetDate()) BETWEEN 0 AND 5 THEN Volume ELSE 0 END) AS [0-5 Days],
SUM(CASE WHEN DATEDIFF(day,[Date],GetDate()) BETWEEN 6 AND 10 THEN Volume ELSE 0 END) AS [6-10 Days],
SUM(CASE WHEN DATEDIFF(day,[Date],GetDate()) BETWEEN 11 AND 15 THEN Volume ELSE 0 END) AS [11-15 Days],
SUM(CASE WHEN DATEDIFF(day,[Date],GetDate()) BETWEEN 16 AND 20 THEN Volume ELSE 0 END) AS [16-20 Days],
SUM(CASE WHEN DATEDIFF(day,[Date],GetDate()) BETWEEN 21 AND 30 THEN Volume ELSE 0 END) AS [21-30 Days],
SUM(Volume) AS Total
FROM yourtable
WHERE [Date] >= CAST(GetDate()-30 AS DATE)
GROUP BY Type WITH ROLLUP

Compare Current Row with Previous/Next row in SQL Server

I have a table named team and it like below: I just added a row_number in the 3rd column
RaidNo OutComeID RN
2 15 1
4 15 2
6 14 3
8 16 4
10 16 5
12 14 6
14 16 7
16 15 8
18 15 9
20 16 10
22 12 11
24 16 12
26 16 13
28 16 14
30 15 15
32 14 16
34 13 17
When the OutcomeId came as 16 then start with one and 16 comes consecutively, add one by one. And the results be like
RaidNo OutComeID RN Result
2 15 1 0
4 15 2 0
6 14 3 0
8 16 4 1
10 16 5 2
12 14 6 0
14 16 7 1
16 15 8 0
18 15 9 0
20 16 10 1
22 12 11 0
24 16 12 1
26 16 13 2
28 16 14 3
30 15 15 0
32 14 16 0
34 13 17 0
Help me to get the result.
You can use the following query:
SELECT RaidNo, OutComeID, RN,
CASE
WHEN OutComeID <> 16 THEN 0
ELSE ROW_NUMBER() OVER (PARTITION BY OutComeID, grp ORDER BY RN)
END AS Result
FROM (
SELECT RaidNo, OutComeID, RN,
RN - ROW_NUMBER() OVER (PARTITION BY OutComeID ORDER BY RN) AS grp
FROM mytable) AS t
ORDER BY RN
Field grp identifies slices (also called islands) of consecutive records having the same OutComeID value. The outer query uses grp in order to enumerate each record that belongs to a '16' slice. The records that belong to the other slices are assigned value 0.
Demo here

Find duplicates on multiple columns in a SQL

I want to find the batchID who are having subjectID(0,1,2) only, pls help me, thanks in advance
I need answer BatchID=12 and BatchID=51, what can I do in sql
MyTable
uid BatchID SubjectID
6 2 0
7 2 1
8 2 2
9 2 4
10 3 0
11 3 1
12 4 5
13 4 0
14 5 5
15 6 5
17 7 0
18 7 1
19 7 2
26 12 0
27 12 1
28 12 2
29 1 0
30 1 1
31 1 4
62 45 5
63 46 0
64 46 1
65 46 4
107 49 6
108 49 2
109 49 4
110 50 1
111 50 3
116 0 1
117 0 4
118 51 0
119 51 1
120 51 2
You can use conditional aggregation for this:
select batchId
from your_table
group by batchId
having count(distinct case when subjectID in (0,1,2) then subjectID end) = 3
and count(case when subjectID not in (0,1,2) then 1 end) = 0
Explanation:
Group by batchId - Aggregate on batchId
count(distinct case when subjectID in (0,1,2) then subjectID end) - Produces 3 only if all three of them are present for this batchId
count(case when subjectID not in (0,1,2) then 1 end) - Produces 0 if there is no other subjectID except 0,1,2 assuming nulls are not allowed in the subjectId column.
You can use Row_Number()
;with cte as (
select *, RowN = row_number() over (partition by batchid order by uid) from #yourbatch where subjectid in (0,1,2)
) select distinct BatchId from cte where RowN > 1