Find intersecting dates - sql

Can somebody help me with next problem. I have MS Access table, lets say with my employees, and for each one of them I have start and end date of their vacation:
Name begin end
John 1.3.2021. 15.3.2021.
Robert 6.3.2021. 8.3.2021.
Lisa 13.3.2021. 16.3.2021.
John 1.4.2021. 3.4.2021.
Robert 2.4.2021. 2.4.2021.
Lisa 15.5.2021. 23.5.2021.
Lisa 5.6.2021. 15.6.2021.
How to get the result with number of employees which are absent from work per each date from the table (dates which are included into intervals begin-end). For example:
1.3.2021. 1 '>>>only John
2.3.2021. 1 '>>>only John
3.3.2021. 1 '>>>only John
4.3.2021. 1 '>>>only John
5.3.2021. 1 '>>>only John
6.3.2021. 2 '>>>John and Robert
7.3.2021. 2 '>>>John and Robert
...
Thank you in advanced!

You can use union to combine the tables and a correlated subquery:
select dte,
(select count(*)
from t
where d.dte between t.[begin] and t.[end]
) as cnt
from (select [begin] as dte
from t
union
select [end]
from t
) d;

Related

Query to get every sample with at least 3 occurrences at every category

I'm struggling to select every patient which has at least 3 visits at every specialist in 2019, but so far all my attempts have failed.
Could someone has any idea how to achieve?
Thanks in advance.
Table A:
PacjentId
Name
Surname
DateOfVisit
SpecializationId
1
john
doe
2019-04-05
1
1
john
doe
2019-05-06
2
2
mary
jane
2019-02-03
1
2
mary
jane
2019-09-07
2
3
mark
twain
2020-01-01
1
...
...
...
...
...
Table B:
Id
NameOfSpecialisation
1
Diabetologist
2
Internist
...
...
You just need a COUNT(DISTINCT in a HAVING clause:
SELECT PacjentId, Name, Surname
FROM A
WHERE DateOfVisit >= '2019-01-01' AND DateOfVisit < '2020-01-01'
GROUP BY PacjentId, Name, Surname
HAVING COUNT(DISTINCT SpecializationId) >= 3
Your table design appears to be denormalized: A represents Visits and B represents Specializations, therefore there should be another Patients table containing Name, Surname

SQL Query: New columns for data with some matching criteria

I'm working with a query that pulls data from a table and arranges it in a manner similar to below:
Query1
BldID UnitID Res1
1 201 John Smith
1 201 Jane Doe
1 202 Daniel Jones
1 202 Mark Garcia
2 201 Maria Lee
2 201 Paul Williams
2 201 Mike Jones
I'd like to modify the query output in SQL/Design so that each resident that shares a building / unit shows as a new column on the same row as shown below:
BldID UnitID Res1 Res2 Res3
1 201 John Smith Jane Doe
1 202 Daniel Jones Mark Garcia
2 201 Maria Lee Paul Williams Mike Jones
I apologize if this is crude/not enough information but any help would be greatly appreciated.
You can try using conditional aggregation
with cte as
(
select *, row_number() over(partition by BldID,UnitID order by Res1) as rn
from tablename
)
select BldID,UnitID,
max(case when rn=1 then Res1 end) as Res1,
max(case when rn=2 then Res1 end) as Res2,
max(case when rn=3 then Res1 end) as Res3
from cte
group by BldID,UnitID
So, drawing from a few different sources, this might work, try pasting this intoa query editor, and see if it'll run.
TRANSFORM MAX(Res1)
SELECT BldID, UnitID
, (
SELECT COUNT(T1.Marks)
FROM tableName AS T1
WHERE
T1.BldgID = T2.BldgID AND
T1.UnitID = T2.UnitID AND
T1.Res1 >= T2.Res1
) AS Rank, Res1
FROM tableName t2
GROUP BY BldID, UnitID
PIVOT Rank;
2 years late, but maybe I can add something, in Access we are surgeons operating with kitchen knifes, things must be done in the Access Way...
I tested it having this table UnitStudentBlock
BldID
UnitID
Res1
1
201
John Smith
1
201
Jane Doe
1
202
Daniel Jones
1
202
Mark Garcia
2
201
Maria Lee
2
201
Paul Williams
2
201
Mike Jones
2
201
Julian Gomes
As Access doesn't have row_number, first I created a table with an auto increment field so that we can have something like a row number:
CREATE TABLE TableWithId
(
Id COUNTER,
BldID INT,
UnitID INT,
Res1 VARCHAR(100),
ResNumber VARCHAR(100)
)
Then I inserted all the data from the initial table into this newly created table:
INSERT INTO TableWithId (BldID, UnitID, Res1)
SELECT *
FROM UnitStudentBlock
ORDER BY BldID,
UnitID
Then I updated everything using DCOUNT to have a row_number partitioned:
UPDATE TableWithId
SET ResNumber = 'Res' + Cstr(DCOUNT("*", "TableWithId", "ID >=" & [ID]
& " AND UnitId = " & [UnitId]
& " AND BldId = " & [BldId]))
And finally we can run the query that returns the data:
TRANSFORM MAX(Res1)
SELECT BldID, UnitID
FROM TableWithId
GROUP BY BldID, UnitID
PIVOT ResNumber

Build time window counters from raw data - Big Query

Consider raw events data regarding purchases in 2020, as per the following table:
BUYER DATE ITEM
Joe '2020-01-15' Dr. Pepper
Joe '2020-02-15' Dr. Pepper
Joe '2020-03-15' Dr. Pepper
Joe '2020-05-15' Dr. Pepper
Joe '2020-10-15' Dr. Pepper
Joe '2020-12-15' Dr. Pepper
I would like to aggregate the data to see what Joe did in a monthly moving sum, i.e., obtaining as an outcome
BUYER Date Num_Purchases_last_3months
Joe '2020-01-31' 1
Joe '2020-02-31' 2
Joe '2020-03-31' 3
Joe '2020-04-31' 2
.
.
.
Joe '2020-11-31' 1
Joe '2020-12-31' 2
How could I obtain the desired result in an efficient query?
You can use window functions, in this case, count(*) with a range window frame specification:
select t.*,
count(*) over (partition by buyer
order by extract(year from date) * 12 + extract(month from date)
range between 2 preceding and current row
) as Num_Purchases_last_3months
from t;

get extra rows for each group where date doesn't exist

I've been playing with this for days, and can't seem to come up with something. I have this query:
select
v.emp_name as Name
,MONTH(v.YearMonth) as m
,v.SalesTotal as Amount
from SalesTotals
Which gives me these results:
Name m Amount
Smith 1 123.50
Smith 2 40.21
Smith 3 444.21
Smith 4 23.21
Jones 1 121.00
Jones 2 499.00
Jones 3 23.23
Jones 4 41.82
etc....
What I need to do is use a JOIN or something, so that I get a NULL value for each month (1-12), for each name:
Name m Amount
Smith 1 123.50
Smith 2 40.21
Smith 3 444.21
Smith 4 23.21
Smith 5 NULL
Smith 6 NULL
Smith ... NULL
Smith 12 NULL
Jones 1 121.00
Jones 2 499.00
Jones 3 23.23
Jones 4 41.82
Jones 5 NULL
Jones ... NULL
Jones 12 NULL
etc....
I have a "Numbers" table, and have tried doing:
select
v.emp_name as Name
,MONTH(v.YearMonth) as m
,v.SalesTotal as Amount
from SalesTotals
FULL JOIN Number n on n.Number = MONTH(v.YearMonth) and n in(1,2,3,4,5,6,7,8,9,10,11,12)
But that only gives me 6 additional NULL rows, where what I want is actually 6 NULL rows for each group of names. I've tried using Group By, but not sure how to use it in a JOIN statement like that, and not even sure if that's the correct route to take.
Any advice or direction is much appreciated!
Here's one way to do it:
select
s.emp_name as Name
,s.Number as m
,st.salestotal as Amount
from (
select distinct emp_name, number
from salestotals, numbers
where number between 1 and 12) s left join salestotals st on
s.emp_name = st.emp_name and s.number = month(st.yearmonth)
Condensed SQL Fiddle
You could do:
SELECT EN.emp_name Name,
N.Number M,
ST.SalesTotal Amount
FROM ( SELECT Number
FROM NumberTable
WHERE Number BETWEEN 1 AND 12) N
CROSS JOIN (SELECT DISTINCT emp_name
FROM SalesTotals) EN
LEFT JOIN SalesTotals ST
ON N.Number = MONTH(ST.YearMonth)
AND EN.emp_name = ST.emp_name

SQL - Return number times a value results from a query

I'm fairly new to SQL server (this is my second post on StackOverflow). I'm currently using SQL Server 2008 R2. I have a few tables that I've joined with the following query:
SELECT pt.first_name, pt.last_name, pt.provider_id,
pt.last_visit_date, pl.last_name
FROM dbo.pm_patient pt
INNER JOIN dbo.ProviderList pl
ON pt.provider_id = pl.provider_id
WHERE pt.last_visit_date >= '02/01/2012' AND pt.last_visit_date <= '02/01/2013'
ORDER BY provider_id
The result of the above query looks something like this:
first_name last_name provider_id last_visit_date last_name
Smith John 1 04/25/2012 Johnson
Doe Jane 1 02/25/2012 Johnson
Davies Ann 1 03/15/2012 Johnson
Dupree David 1 11/20/2012 Johnson
Jones Becky 1 04/21/2012 Smith
Diaz Mike 1 02/12/2012 Smith
Williams Allison 1 08/05/2012 Smith
Taylor Joe 1 10/01/2012 Smith
I would rather simply get the following result:
last_name NoOfPatients
Johnson 4
Smith 4
Could someone please help me?
Try :
SELECT pl.last_name, count(*) NoOfPatients
FROM dbo.pm_patient pt
INNER JOIN dbo.ProviderList pl
ON pt.provider_id = pl.provider_id
WHERE pt.last_visit_date >= '02/01/2012' AND pt.last_visit_date <= '02/01/2013'
GROUP BY pl.last_name
You need to read about how to use group in querys, basically what you need to do is count the number of patients and group by providers.
SELECT pt.last_name, COUNT(pt.*) NoOfPatients
FROM dbo.pm_patient pt
INNER JOIN dbo.ProviderList pl
ON pt.provider_id = pl.provider_id
WHERE pt.last_visit_date >= '02/01/2012' AND pt.last_visit_date <= '02/01/2013'
ORDER BY provider_id
GROUP BY pt.last_name