I'm using SSMS and SSRS 2018. I need to create a Headcount Report in SSRS. Ideally it will have 2 date parameters #DateFrom and #DateTo where we can count how many people were employed in the business between certain dates, leavers will need to be included if they were still in employment between the dates chosen. Below is the dataset
ID Name ContractStart ContractEnd Department status
1 Bob Masters 2013-07-01 2013-07-23 ICT Leaver
1 Bob Masters 2013-07-24 2018-01-02 BIT Leaver
2 Kate Williams 2021-02-01 NULL Stores Active
3 Sam Power 2015-03-02 2016-05-01 ICT Active
3 Sam Power 2016-05-02 2018-03-01 ICT Active
3 Sam Power 2018-03-02 NULL ICT Active
4 Becky Smith 2021-09-10 NULL Finance Active
5 Debbie Glover 2019-11-11 2020-01-01 HR Leaver
5 Debbie Glover 2020-06-07 2022-01-01 HR Leaver
6 Helen Stewart 2020-02-05 NULL ICT Active
6 Helen Stewart 2021-04-09 NULL Stores Active
7 Izzy Andrews 2017-06-10 2022-10-01 HR Active
Things to note
ID 6 has 2 open contracts so would need to be counted twice
ID 7 is currently still active, though has an end date in the future
Ideally need help with the parameter as I'm only used to dealing with the example below
Where date between #datefrom and #dateto
You can check if the datefrom is before the contract end date (or the contract end date is NULL), and the dateto should be after the contract start date:
WHERE (#datefrom <= ContractEnd OR ContractEnd IS NULL)
AND #dateto >= ContractStart;
SELECT Count(*) as ActiveEmployeeCount
FROM
(SELECT ID, Name, ContractStart, EndDate = ISNULL(ContractEnd, '9999-01-01'), Department, [status] FROM myTable) a
WHERE (a.ContractStart <= #DateTo and EndDate >= #DateFrom)
Related
I have a scenario in below:
Name
LoginDate
Peter
2020-01-01
Peter
2020-01-02
Mary
2020-01-01
Peter
2020-02-02
Mary
2020-02-05
Chris
2020-02-07
How to write the SQL which can be re-organized in below
Name
Jan
Feb
Peter
2
1
Mary
1
1
Chris
0
1
Appreciated your help!
We can use Month() to do it
create table login_record(
name varchar(100),
login_date date
);
insert into login_record(name,login_date) values
('Peter','2020-01-01'),
('Peter','2020-01-02'),
('Mary','2020-01-01'),
('Peter','2020-02-02'),
('Mary','2020-02-05'),
('Chris','2020-02-07');
SELECT
name,
SUM(IF(month(login_date) = 1,1,0)) AS `Jan`,
SUM(IF(month(login_date) = 2,1,0)) AS `Feb`,
SUM(IF(month(login_date) = 3,1,0)) AS `Mar`
-- sum other month
FROM login_record
group by name
order by name
DB Fiddle Demo
I have a table named employee experience with id, userId, startDate, endDate columns.
I want to calculate employee experience. Can someone please help with mysql query or JPA specification code?
For example in case of following data:
id
userID
startDate
endDate
1
1
2021-01-01
2022-01-01
2
2
2019-01-01
2020-01-01
3
2
2020-01-02
2021-01-01
4
3
2021-01-01
2022-01-01
the output should be:
userID
experience
1
1
2
2
3
1
Successfully did this with the following:
SELECT SUM(TIMESTAMPDIFF(YEAR, START_DATE, END_DATE)) AS experience,
SOCIAL_PROFILE_ID
FROM tableName
GROUP BY SOCIAL_PROFILE_ID
EDIT: I have added the primary key, following the comment by #Strawberry
The aim is to return the number of current members, and also the number of past memberships, on any particular date/time.
For example, suppose we have
msid id start cancelled
1 1 2020-01-01 09:00:00 null
2 2 2020-01-01 09:00:00 2020-12-31 09:00:00
3 2 2021-01-01 09:00:00 null
4 3 2020-01-01 09:00:00 2020-06-30 09:00:00
5 3 2020-02-01 09:00:00 2020-06-30 09:00:00
6 3 2020-07-01 09:00:00 null
and we want to calculate the number of members at various times, which should return as follows
Datetime Current Past <Notes - not to be returned by the query>
2020-01-01 12:00:00 3 0 -- all 3 IDs have joined earlier on this date
2020-02-01 12:00:00 3 0 -- new membership for existing member (ID 3) is not counted
2020-06-30 12:00:00 2 1 -- ID 3 has cancelled earlier on this day
2020-07-01 12:00:00 3 0 -- ID 3 has re-joined earlier on this day
2020-12-31 12:00:00 2 1 -- ID 2 has cancelled earlier on this day
2021-01-01 12:00:00 3 0 -- ID 2 has re-joined earlier on this day
An ID may either be current or past, but never both. That is, if a past member re-joins, as in the case of ID 2 and 3 above, they become current members, and are no longer past members.
Also, a member may have multiple current memberships, but they can only be counted as a current member once, as in the case of ID 3 above.
How can this be achieved in MySQL ?
Here is a db<>fiddle with the above data
Test this:
WITH
cte1 AS ( SELECT start `timestamp` FROM dt
UNION
SELECT cancelled FROM dt WHERE cancelled IS NOT NULL ),
cte2 AS ( SELECT DISTINCT id
FROM dt )
SELECT cte1.`timestamp`, COUNT(DISTINCT dt.id) current, SUM(dt.id IS NULL) past
FROM cte1
CROSS JOIN cte2
LEFT JOIN dt ON cte1.`timestamp` >= dt.start
AND (cte1.`timestamp` < dt.cancelled OR dt.cancelled IS NULL)
AND cte2.id = dt.id
GROUP BY cte1.`timestamp`
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=942e4c97951ed0929e178134ef67ce69
I have two tables with client info:
Portfolios
accountId Date portfolio
Barney 2013-06-28 Slate
Barney 2013-07-01 Bedrock
Barney 2013-07-02 Bedrock
Fred 2013-06-28 Slate
Fred 2013-07-01 Slate
Fred 2013-07-02 Slate
Money
accountId Date value
Barney 2013-06-28 $100.00
Barney 2013-07-01 $101.00
Barney 2013-07-02 $103.00
Fred 2013-06-28 $500.00
Fred 2013-07-01 $503.00
Fred 2013-07-02 $498.00
I want to sum by date the portfolio values for each strategy - Slate and Bedrock. I can compare the two and get the running values for a particular strategy. For example:
SELECT Portfolios.accountId, Portfolios.Date, Portfolios.strategy,
Money.accountId, Money.Date, Money.strategy, SUM(Money.value) as sumtotal
from Money, Portfolios
WHERE Money.accountId = Portfolios.accountId
AND Money.Date = Portfolios.Date
AND Portfolio.portfolio = 'Slate'
GROUP BY Date ORDER by Date ASC
This works.
Date value
2013-06-28 $600.00
2013-07-01 $503.00
2013-07-02 $498.00
What I cannot get to work is comparing strategies across dates:
SUM (Money.value) WHERE Portfolios.strategy.date != Portfolios.strategy.date (-1)
GROUP BY Date
so that the query would ONLY return $100 (the last value of Barney's portfolio on 2013-06-28 before he switched strategies.
I've a user table (MySQL) with the following data
id email creation_date
1 bob#mail.com 2011-08-01 09:00:00
2 bob#mail.com 2011-06-24 02:00:00
3 john#mail.com 2011-02-01 04:00:00
4 john#mail.com 2011-08-05 20:30:00
5 john#mail.com 2011-08-05 23:00:00
6 jill#mail.com 2011-08-01 00:00:00
As you can see we allow email duplicates so its possible to register several accounts with the same email address.
Now I need to select all adresses ordered by the creation_date but no duplicates. This is easy (i think)
SELECT * FROM (SELECT * FROM users ORDER BY creation_date) AS X GROUP BY email
Expected result:
id email creation_date
2 bob#mail.com 2011-06-24 02:00:00
6 jill#mail.com 2011-08-01 00:00:00
3 john#mail.com 2011-02-01 04:00:00
But then I also need to select all other adresses, ie. all that are not present in the result from the first query. Duplicate are allowed here.
Expected result:
id email creation_date
1 bob#mail.com 2011-08-01 09:00:00
4 john#mail.com 2011-08-05 20:30:00
5 john#mail.com 2011-08-05 23:00:00
Any ideas? Perfomance is important because the real database is very huge
SELECT * FROM a
FROM users a
LEFT JOIN (SELECT email, MIN(creation_date) as min_date GROUP BY email)x ON
(x.email = a.email AND x.min_date=a.creation_date)
WHERE x.email IS NULL
In SQL server we would do a Select statement using a rank.
Here are some MYSQL samples:
How to perform grouped ranking in MySQL
http://thinkdiff.net/mysql/how-to-get-rank-using-mysql-query/
I hope this helps.