{
delimiter &&
CREATE PROCEDURE `BPM_CLMBR_RPT_PROC` (IN customer_id INT,IN fromdate date,IN todate date)
BEGIN
-- distingushing the columns up,didntmove,down as well as group concatination
SELECT
RESPONSEDATE ,
ifnull(GROUP_CONCAT(CLIMBER, ''),0) AS 'up',
ifnull(GROUP_CONCAT(STATIC, ''),0) AS 'didntmove',
ifnull(GROUP_CONCAT(FALLER, ''),0) AS 'down',
ID
FROM
(
-- transposing the rows to column
SELECT
CASE
WHEN report = 'STATIC' THEN count
END AS 'STATIC',
CASE
WHEN report = 'CLIMBER' THEN count
END AS 'CLIMBER',
CASE
WHEN REPORT = 'FALLER' THEN COUNT
END AS 'FALLER',
RESPONSEDATE,
ID
FROM
(
-- counting the number of records in STATIC,CLIMBER,FALLER
SELECT
REPORT,RESPONSEDATE,COUNT(REPORT) count,ID
FROM (
-- grouping the records into STATIC,CLIMBER and FALLER
SELECT
CASE
WHEN (FNL.PREVIOUS_SCORE BETWEEN 0 AND 6 AND FNL.CURRENT_SCORE BETWEEN 0 AND 6) THEN 'STATIC'
WHEN (FNL.PREVIOUS_SCORE BETWEEN 7 AND 8 AND FNL.CURRENT_SCORE BETWEEN 7 AND 8) THEN 'STATIC'
WHEN (FNL.PREVIOUS_SCORE BETWEEN 9 AND 10 AND FNL.CURRENT_SCORE BETWEEN 9 AND 10) THEN 'STATIC'
WHEN (FNL.PREVIOUS_SCORE BETWEEN 0 AND 6 AND FNL.CURRENT_SCORE BETWEEN 7 AND 8) THEN 'CLIMBER'
WHEN (FNL.PREVIOUS_SCORE BETWEEN 0 AND 6 AND FNL.CURRENT_SCORE BETWEEN 9 AND 10) THEN 'CLIMBER'
WHEN (FNL.PREVIOUS_SCORE BETWEEN 7 AND 8 AND FNL.CURRENT_SCORE BETWEEN 9 AND 10) THEN 'CLIMBER'
WHEN (FNL.PREVIOUS_SCORE BETWEEN 7 AND 8 AND FNL.CURRENT_SCORE BETWEEN 0 AND 6) THEN 'FALLER'
WHEN (FNL.PREVIOUS_SCORE BETWEEN 9 AND 10 AND FNL.CURRENT_SCORE BETWEEN 0 AND 6) THEN 'FALLER'
WHEN (FNL.PREVIOUS_SCORE BETWEEN 9 AND 10 AND FNL.CURRENT_SCORE BETWEEN 7 AND 8) THEN 'FALLER'
END AS 'REPORT',
FNL.RESPONSEDATE,
ID
FROM (
SELECT
-- group concatination using space but only one client responses is expected
CLIENTID,
CLIENTNAME,
GROUP_CONCAT(TEMP.CURRENT_SCORE, '') AS 'CURRENT_SCORE',
GROUP_CONCAT(TEMP.PREVIOUS_SCORE, '') AS 'PREVIOUS_SCORE',
GROUP_CONCAT(TEMP.COMMENT,'') AS 'COMMENT',
max(id) ID,
max(responsedate) RESPONSEDATE
FROM
(
-- Top two npsscores are taken into account and only 1st comment is taken
SELECT
CLIENTID,id,CLIENTNAME,
CASE
WHEN RANK = 1 THEN npsscore
END AS 'CURRENT_SCORE',
CASE
WHEN RANK = 2 THEN npsscore
END AS 'PREVIOUS_SCORE',
CASE
WHEN RANK=1 THEN COMMENT
END AS 'COMMENT',
RESPONSEDATE
FROM
(
-- NPS_CLIENT_STATUS is calculated and only the 1st and 2nd rank holders are selected
SELECT
CLMBR_RPT.*,CASE
WHEN CLMBR_RPT.NPSSCORE BETWEEN 0 AND 6 THEN 'DETRACTOR'
WHEN CLMBR_RPT.NPSSCORE BETWEEN 7 AND 8 THEN 'PASSIVE'
ELSE 'PROMOTER'
END 'NPS_CLIENT_STATUS'
FROM
(
-- rank funtion is in corporated rownum() in Oracle
SELECT
a.*,
(CASE a.CLIENTID
WHEN #curType THEN #curRow:=#curRow + 1
ELSE #curRow:=1 AND #curType:=a.CLIENTID
END) AS rank
FROM
(SELECT
NSR.*
FROM
nps_summary_report NSR
INNER JOIN
-- innerjoin is done to get all the client id for a given date span which jas multiple records in the nps_summary_report table
-- joined with nps_summary_report table will eliminate all the records in the nps_summary_report table which is not having
-- customerid , multiple responses and date
-- this is the innermost query and will execute first and eliminate all the unwanted records
(SELECT
CLIENTID
FROM
nps_summary_report
WHERE CUSTOMERID=customer_id -- TO BE PROVIDED
-- AND RESPONSEDATE between STR_TO_DATE(fromdate, '%m/%d/%Y') AND STR_TO_DATE(todate, '%m/%d/%Y') -- TO BE PROVIDED
AND RESPONSEDATE > fromdate and RESPONSEDATE< todate -- TO BE PROVIDED
-- AND RESPONSEDATE BETWEEN date_format(STR_TO_DATE(#fromdate, '%m/%d/%Y'),'%Y-%m-%d') AND date_format(STR_TO_DATE(#todate, '%m/%d/%Y'),'%Y-%m-%d')
-- AND RESPONSEDATE BETWEEN date_format(#fromdate,'%Y-%m-%d') AND date_format(#todate,'%Y-%m-%d')
GROUP BY CLIENTID
HAVING COUNT(*) > 1) CLNT_ID ON CLNT_ID.CLIENTID = NSR.CLIENTID ) a, -- REMOVING ALL THE CLIENT WHICH HAVE 1 FEEDBACK
(SELECT #curRow:=0, #curType:='') r
WHERE CUSTOMERID=customer_id -- RETREIVE ALL DATA FOR BOOKMYSHOW ONLY
ORDER BY CLIENTID , RESPONSEDATE ) CLMBR_RPT
WHERE
CLMBR_RPT.RANK BETWEEN 0 AND 2)STG_BMS_CLIMBER_RPT
GROUP BY CLIENTID , CASE
WHEN RANK = 1 THEN npsscore
END , CASE
WHEN RANK = 2 THEN npsscore
END,CASE
WHEN RANK=1 THEN COMMENT
END
) TEMP
GROUP BY CLIENTID) FNL ) TBL
GROUP BY RESPONSEDATE,REPORT)stg_temp) TEMP
GROUP BY RESPONSEDATE
order by RESPONSEDATE desc;
END
&&
delimiter ; }
I am calling the stored procedure by
{ call BPM_CLMBR_RPT_PROC(6,str_to_date('2015-10-01','%Y-%m-%d'),str_to_date('2015-12-31','%Y-%m-%d')); }
The query is returning all the records irrespective of the date constraints .But when a hard coded value is passed inside the code like
{
RESPONSEDATE BETWEEN date_format(STR_TO_DATE('11/1/2015', '%m/%d/%Y'),'%Y-%m-%d') AND date_format(STR_TO_DATE('12/13/2015', '%m/%d/%Y'),'%Y-%m-%d')
}
then the expected result is comming.
Related
I am trying to Get employees who received a raise in 2 consecutive years, in this case employee 1000 is the right answer.
here is the data and the sql i have tried.
EID
SALARY
YEAR
1000
10,000
2016
1000
7,500
2015
1000
6,000
2014
1001
8,000
2016
1001
7,500
2015
1002
7,500
2016
1002
7,500
2015
1002
5,000
2014
1003
6,000
2016
1003
7,000
2015
1003
5,000
2014
i have used following code however it gets only row number by EID and not calcualtion of last year and present year, i need to find employee who got raise in 2 consecutive years.
output
select * ,
row_number() over(partition by eid order by salary and year desc)as rn
from gs;
You can do it using the LEAD window function that compute the two consecutive previous value of the salary. Then you can check how many employees have at least one row with salary1 < salary2 < salary3.
SELECT DISTINCT
eid
FROM (
SELECT
eid,
year,
salary,
(LEAD(salary, 1) OVER(PARTITION BY eid ORDER BY year DESC)) AS prev_salary1,
(LEAD(salary, 2) OVER(PARTITION BY eid ORDER BY year DESC)) AS prev_salary2
FROM
employees
) consecutive3
WHERE
salary > prev_salary1
AND
prev_salary1 > prev_salary2
The assumption is that there are no missing years for which a salary of a dependent was not recorded.
Here's the fiddle: https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=8c0d8a1deec8e77bb32a173656c3e386.
EDIT: Detailed explanation
Let's do the example of Jennifer, who has worked for five years and got these salaries:
2018 -> 65000
2017 -> 55000
2016 -> 50000
She's a candidate for being selected as her salary was raised three times consecutively.
1. LEAD(salary, 1) OVER(PARTITION BY eid ORDER BY year DESC)
Allows you to get the salary for year "Y" and the salary for year "Y-1":
("year" -> "salary", "previous_salary")
2018 -> 65000 , 55000
2017 -> 55000 , 50000
2016 -> 50000 , NULL
2. LEAD(salary, 2) OVER(PARTITION BY eid ORDER BY year DESC)
Allows you to get the salary for year "Y" and the salary for year "Y-1":
("year" -> "salary", "previous_salary", "previous_salary_by_2_years")
2018 -> 65000 , 55000 , 50000
2017 -> 55000 , 50000 , NULL
2016 -> 50000 , NULL , NULL
3. WHERE salary > prev_salary1 AND prev_salary1 > prev_salary2
Some filtering on the employees who
have their year3 salary higher than their year2 salary (salary > prev_salary1)
have their year2 salary higher than their year1 salary (prev_salary1 > prev_salary2)
I know that this has already been answered but here is my take using the lag function to determine if there was an increase from the previous year and ran that twice.
SELECT *
FROM (
SELECT
t2.*,
LAG(increase) over (partition by eid order by year) AS increaseNextYear
FROM (
SELECT
t1.*,
COALESCE(salary - LAG(salary) over (partition by eid order by year), 0) > 0 AS increase
FROM tbl_test t1
) as t2
) t3 where increase AND increaseNextYear
with
dates as
(
select
a.*,
dense_rank() OVER (
partition by eid
order by year desc, salary
)
as rn,
case
when
lead(salary,2)over(partition by eid order by year, salary)
>
lead(salary,1)over(partition by eid order by year, salary)
and
lead(salary,1)over(partition by eid order by year, salary)
>
salary
then
1
else
0
end
as flag
from
employees a
)
select
eid
from
dates
where
rn = 3
and flag = 1
Not a beautiful query, but straight-forward: find employees who had a salary in a year where the salary in the previous year was lower and the salary in the year before that even lower. Using LAG is more elegant, but I thought I'd throw this in, just to show an alternative.
select *
from employee
where exists
(
select null
from gs
where gs.eid = employee.id
and exists
(
select null
from gs prev
where prev.eid = gs.eid
and prev.year = gs.year - 1
and prev.salary < gs.salary
and exists
(
select null
from gs prevprev
where prevprev.eid = prev.eid
and prevprev.year = prev.year - 1
and prevprev.salary < prev.salary
)
)
);
Same thing with a join:
select *
from employee
where exists
(
select null
from gs
join gs prev on prev.eid = gs.eid
and prev.year = gs.year - 1
and prev.salary < gs.salary
join gs prevprev on prevprev.eid = prev.eid
and prevprev.year = prev.year - 1
and prevprev.salary < prev.salary
where gs.eid = employee.id
);
For versions prior to 8.0 (mine is 5.7) which lack the cutting edge features of the newer one, I tried a procedure to accomplish the job. First and foremost, get all the eid which have no less than three years' salary record, which is the minimum requirement of the consecutive bonus. The rest is to fetch and compare using a cursor from the eid pool. The result is stored in a temporary table t .
delimiter //
drop procedure if exists lucky_emp//
create procedure lucky_emp()
begin
declare old_eid int default 0;
declare old_salary int;
declare new_eid int ;
declare new_salary int;
declare bonus_year int;
declare fin bool default false;
declare c cursor for select eid,salary from salary where eid in(select eid from salary group by eid having count(eid)>=3) order by eid,year;
declare continue handler for not found set fin=true;
drop temporary table if exists t ;
create temporary table t (t_eid int);
open c;
lp:loop
fetch c into new_eid ,new_salary;
if fin=true then
leave lp;
end if;
if new_eid !=old_eid then
set old_eid=new_eid,old_salary=0,bonus_year=0;
end if;
if new_salary> old_salary then
set bonus_year=bonus_year+1,old_salary=new_salary;
else
set bonus_year=0;
end if;
if bonus_year=3 and new_eid not in(select t_eid from t) then
insert t values(new_eid);
end if;
end loop lp;
end//
delimiter ;
select * from t ;
Select a.*, b.prev_sal1, b.prev_sal2
from employees a
join (
Select eid ,year,
lag(salary,1) over (partition by eid order by year) as prev_sal1,
lag(salary,2) over (partition by eid order by year) as prev_sal2
from employees ) b
on a.eid=b.eid
and a.year = b.year
where salary>prev_sal1 and prev_sal1>prev_sal2
fiddle: https://dbfiddle.uk/rfGv31zM
I have table:
ID STATUS
----------
0 0
1 1
2 0
3 1
4 2
5 2
6 0
7 3
8 2
9 0
10 1 etc.
I want to get only first occurences of 1 and 2 when they change state (I mean 0 and 3 are not important to me) - so in this case I should get ids: 1, 4, 10. I tried group by but it only groups all values by 1 or 2, and not just the cases when states has changed.
Any idea please how to specify mysql query?
So, it's a slow day...
SELECT MIN(id)
FROM
( SELECT x.*
, CASE WHEN #prev=status THEN #i:=#i ELSE #i:=#i+1 END i
, #prev:=status prev
FROM
( SELECT *
FROM my_table
WHERE status IN (1,2)
) x
JOIN
( SELECT #prev:=1,#i:=1 ) vars
ORDER
BY id
) a
GROUP
BY i;
SELECT id
, status
, if( status = #switch
and if( #switch = 1, #switch:=2, #switch:=1 ) in(1,2)
, 1
, 0
) sw
FROM status
JOIN( SELECT #switch :=1 ) t
WHERE status in (1,2)
HAVING sw=1
ORDER BY id
I've got two tables, a project table and a calendar table. The first containts a startdate and days required. The calendar table contains the usual date information, like date, dayofweek, and a column is workingday, which shows if the day is a saturday, sunday, or bank holiday (value = 0) or a regular workday (value = 1).
For a certain report I need write a stored procedure that calculates the predicted enddate by adding the number of estimated workddays needed.
Example:
**Projects**
Name Start_Planned Work_days_Required
Project A 02.05.2016 6
Calendar (04.05 is a bank holdiday)
Day Weekday Workingday
01.05.2016 7 0
02.05.2016 1 1
03.05.2016 2 1
04.05.2016 3 0
05.05.2016 4 1
06.05.2016 5 1
07.05.2016 6 0
08.05.2016 7 0
09.05.2016 1 1
10.05.2016 2 1
Let's say, the estimated number of days required is given as 6 (which leads to the predicted enddate of 10.05.2016). Is it possible to join the tables in a way, which allows me to put something like
select date as enddate_predicted
from calendar
join projects
where number_of_days = 6
I would post some more code, but I'm quite stuck on how where to start.
Thanks!
You could get all working days after your first date, then apply ROW_NUMBER() to get the number of days for each date:
SELECT Date, DayNum = ROW_NUMBER() OVER(ORDER BY Date)
FROM Calendar
WHERE IsWorkingDay = 1
AND Date >= #StartPlanned
Then it would just be a case of filtering for the 6th day:
DECLARE #StartPlanned DATE = '20160502',
#Days INT = 6;
SELECT Date
FROM ( SELECT Date, DayNum = ROW_NUMBER() OVER(ORDER BY Date)
FROM Calendar
WHERE WorkingDay = 1
AND Date >= #StartPlanned
) AS c
WHERE c.DayNum = #Days;
It's not part of the question, but for future proofing this is easier to acheive in SQL Server 2012+ with OFFSET/FETCH
DECLARE #StartPlanned DATE = '20160502',
#Days INT = 6;
SELECT Date
FROM dbo.Calendar
WHERE Date >= #StartPlanned
AND WorkingDay = 1
ORDER BY Date
OFFSET (#Days - 1) ROWS FETCH NEXT 1 ROWS ONLY
ADDENDUM
I missed the part earlier about having another table, and the comment about putting it into a cursor has prompted me to amend my answer. I would add a new column to your calendar table called WorkingDayRank:
ALTER TABLE dbo.Calendar ADD WorkingDayRank INT NULL;
GO
UPDATE c
SET WorkingDayRank = wdr
FROM ( SELECT Date, wdr = ROW_NUMBER() OVER(ORDER BY Date)
FROM dbo.Calendar
WHERE WorkingDay = 1
) AS c;
This can be done on the fly, but you will get better performance with it stored as a value, then your query becomes:
SELECT p.Name,
p.Start_Planned,
p.Work_days_Required,
EndDate = c2.Date
FROM Projects AS P
INNER JOIN dbo.Calendar AS c1
ON c1.Date = p.Start_Planned
INNER JOIN dbo.Calendar AS c2
ON c2.WorkingDayRank = c1.WorkingDayRank + p.Work_days_Required - 1;
This simply gets the working day rank of your start date, and finds the number of days ahead specified by the project by joining on WorkingDayRank (-1 because you want the end date inclusive of the range)
This will fail, if you ever plan to start your project on a non working day though, so a more robust solution might be:
SELECT p.Name,
p.Start_Planned,
p.Work_days_Required,
EndDate = c2.Date
FROM Projects AS P
CROSS APPLY
( SELECT TOP 1 c1.Date, c1.WorkingDayRank
FROM dbo.Calendar AS c1
WHERE c1.Date >= p.Start_Planned
AND c1.WorkingDay = 1
ORDER BY c1.Date
) AS c1
INNER JOIN dbo.Calendar AS c2
ON c2.WorkingDayRank = c1.WorkingDayRank + p.Work_days_Required - 1;
This uses CROSS APPLY to get the next working day on or after your project start date, then applies the same join as before.
This query returns a table with a predicted enddate for each project
select name,min(day) as predicted_enddate from (
select c.day,p.name from dbo.Calendar c
join dbo.Calendar c2 on c.day>=c2.day
join dbo.Projects p on p.start_planned<=c.day and p.start_planned<=c2.day
group by c.day,p.work_days_required,p.name
having sum(c2.workingday)=p.work_days_required
) a
group by name
--This gives me info about all projects
select p.projectname,p.Start_Planned ,c.date,
from calendar c
join
projects o
on c.date=dateadd(days,p.Work_days_Required,p.Start_Planned)
and c.isworkingday=1
now you can use CTE like below or wrap this in a procedure
;with cte
as
(
Select
p.projectnam
p.Start_Planned ,
c.date,datediff(days,p.Start_Planned,c.date) as nooffdays
from calendar c
join
projects o
on c.date=dateadd(days,p.Work_days_Required,p.Start_Planned)
and c.isworkingday=1
)
select * from cte where nooffdays=6
use below logic
CREATE TABLE #proj(Name varchar(50),Start_Planned date,
Work_days_Required int)
insert into #proj
values('Project A','02.05.2016',6)
CReATE TABLE #Calendar(Day date,Weekday int,Workingday bit)
insert into #Calendar
values('01.05.2016',7,0),
('02.05.2016',1,1),
('03.05.2016',2,1),
('04.05.2016',3,0),
('05.05.2016',4,1),
('06.05.2016',5,1),
('07.05.2016',6,0),
('08.05.2016',7,0),
('09.05.2016',1,1),
('10.05.2016',2,1)
DECLARE #req_day int = 3
DECLARE #date date = '02.05.2016'
--SELECT #req_day = Work_days_Required FROM #proj where Start_Planned = #date
select *,row_number() over(order by [day] desc) as cnt
from #Calendar
where Workingday = 1
and [Day] > #date
SELECT *
FROM
(
select *,row_number() over(order by [day] desc) as cnt
from #Calendar
where Workingday = 1
and [Day] > #date
)a
where cnt = #req_day
I have a query which returns result of number of calls made by customers and some suggestions made for customers and etc.. for that particular date ie... grouping it by date
But now I want to find number of customers I tried grouping by lead_id and cuncat(lead_id,timecreatredFormat) still there is a data mismatch
Below is the query that I have tried
select
sum(t.enquiry_cnt),
sum(t.suggested_cnt),
sum(t.tot_cnt)
from
(select
case
when source = 1 then 1
else 0
end enquiry_cnt,
case
when source = 6 then 1
else 0
end suggested_cnt,
case
when (source = 1 || source = 6) then 1
else 0
end tot_cnt,
date_format(timecreated, '%d-%b-%Y') created_time,
lead_id,timecreated
from
mg_lead_suggested_listing group by concat(created_time,lead_id) ) t
group by t.created_time
order by t.timecreated desc
limit 10;
Thanks in advance
Check whether following query is correct or not. I have added COUNT(DISTINCT t.lead_id) to get customer count.
DECLARE #TEMP TABLE
(
[source] INT,
lead_id INT,
timecreated DATETIME
)
INSERT INTO #TEMP VALUES (1,1,GETDATE())
INSERT INTO #TEMP VALUES (6,1,GETDATE())
INSERT INTO #TEMP VALUES (6,1,GETDATE())
INSERT INTO #TEMP VALUES (1,2,DATEADD(d,-1,GETDATE()))
INSERT INTO #TEMP VALUES (1,1,DATEADD(d,-1,GETDATE()))
INSERT INTO #TEMP VALUES (1,1,DATEADD(d,-1,GETDATE()))
SELECT
CAST(t.timecreated AS DATE) [date],
SUM(t.enquiry_cnt) enquiry_cnt,
(SELECT COUNT(DISTINCT lead_id) FROM #TEMP WHERE CAST(timecreated AS DATE) = CAST(t.timecreated AS DATE) AND [source] = 1) as lead_enquiry_cnt,
SUM(t.suggested_cnt) suggested_cnt,
(SELECT COUNT(DISTINCT lead_id) FROM #TEMP WHERE CAST(timecreated AS DATE) = CAST(t.timecreated AS DATE) AND [source] = 6) as lead_suggested_cnt,
SUM(t.tot_cnt) tot_cnt,
COUNT(t.lead_id) as lead_cnt
FROM
(
SELECT
CASE
WHEN [source] = 1 THEN 1
ELSE 0
END enquiry_cnt,
CASE
WHEN [source] = 6 THEN 1
ELSE 0
END suggested_cnt,
CASE
WHEN ([source] = 1 OR [source] = 6) THEN 1
ELSE 0
END tot_cnt,
lead_id,
timecreated
FROM
#TEMP
) AS t
group by
CAST(t.timecreated AS DATE)
order by
[date] desc
I have written the following query:
DECLARE #countryCode TINYINT
SET #countryCode = 1;
SELECT
DivingSite.SiteCode,
DATEPART(Month, divingDate) AS 'month number' ,
COUNT (divingNo) AS 'number of dives in month'
FROM
DivingSite
INNER JOIN
tblDiving ON DivingSite.SiteCode = tblDiving.SiteCode
WHERE
DivingSite.countryCode = #countryCode
AND divingDate > DATEADD(year, -1, GETDATE())
GROUP BY
DivingSite.SiteCode, DATEPART(Month, divingDate)
The result of this query is:
siteCode | month number | number of dives in month
--------------------------------------------------
107 1 1
108 7 2
107 8 2
The thing is - for every siteCode I want to display only the month with the biggest number of dives. So I would like to have the result:
siteCode | month number | number of dives in month
--------------------------------------------------
108 7 2
107 8 2
How do I do that?
Try this - use a CTE (Common Table Expression) with a ROW_NUMBER function that "partitions" your data by the siteCode and numbers each row for a single siteCode starting at one - with the one with the highest number of dives having RowNum = 1 and any others having higher row numbers.
By selecting only those rows with RowNum = 1 you get only those entries for each siteCode with the highest number of dives.
DECLARE #countryCode TINYINT
SET #countryCode = 1;
;WITH RawData AS
(
SELECT
ds.SiteCode,
MonthNumber = DATEPART(Month, divingDate),
NumberOfDives = COUNT (divingNo),
RowNum = ROW_NUMBER() OVER (PARTITION BY ds.SiteCode ORDER BY COUNT(divingNo) DESC)
FROM
dbo.DivingSite ds
INNER JOIN
dbo.tblDiving d ON ds.SiteCode = d.SiteCode
WHERE
ds.countryCode = #countryCode
AND divingDate > DATEADD(year, -1, GETDATE())
GROUP BY
ds.SiteCode, DATEPART(Month, divingDate)
)
SELECT
SiteCode,
MonthNumber,
NumberOfDives
FROM
RawData
WHERE
RowNum = 1
You could create a query on top of the one you already have, like so:
select
DivingSite.SiteCode,
DATEPART(Month, divingDate) as 'month number' ,
count (divingNo) as 'number of dives in month'
into #dives
from DivingSite
inner join tblDiving on DivingSite.SiteCode = tblDiving.SiteCode
where
DivingSite.countryCode = #countryCode
and divingDate > DATEADD(year,-1,GETDATE())
group by
DivingSite.SiteCode,
DATEPART(Month, divingDate)
select d.* from #dives d join
(
SELECT
SiteCode,
MAX([number of dives in month]) MaxDives
FROM #dives
GROUP BY SiteCode
) max_dives on max_dives.SiteCode = d.SiteCode
and d.[number of dives in month] = max_dives.MaxDives