Find status from separate fact table - sql

This is in snowflake, but I can figure out any other syntax that is similar.
I have a table of employees and the date they received a paycheck
EMP_ID
Check_dt
1
10-7-2021
2
9-28-2021
1
3-1-2021
And a table that has employee history for full/part time status changes, and the date the change was made effective
EMP_ID
Status
Effective Date
1
F
1/1/20201
2
P
1/1/2021
1
P
6/1/2021
(In this example, employee 1 changed from full to part time halfway through the year)
I want to get the status (F/P) of the employee at the time they received their paycheck.
The output I want is:
EMP_ID
Check_dt
Status
1
10-7-2021
P
2
9-28-2021
P
1
3-1-2021
F
Thanks in advance!

Try this
Select empid, case when t1.chkdate<= (Select
max(effect_date) from
table2 where empid=t1.empid) then t1.status) end as
status
From table1 t1

Related

Access Query: Subtract last 2 values, specific to ID

Help appreciated! My table is setup as follows:
fake data TableName = GAD7
[PatientID Date Value
Sam 10/21/2022 15
George 06/12/2022 7
Luke 09/03/2021 11
Sam 05/15/2020 20
George 12/02/2017 2
George 01/01/1992 6][1]
So I have potentially multiple rows of the same patient, w/different dates.
I need to create a query that subtracts the LAST 2/most recent values for each patient.
So my query would show only those with 2+ records. Negative values are fine/expected.
My successful query would then show:
PatientID (LastScore - 2nd_toLastScore)
Sam -5.0
George 5.0
Luke is not shown because he only has one value
I was able to formulate a query to show only those PatientIDs with >= 2 records and last date and last value. I am not sure how to get the second from last date/value AND THEN subtract those values.
Access query
The SQL view :
SELECT GAD7.PatientID, Count(GAD7.PatientID) AS CountOfPatientID, Last(GAD7.TestDate) AS LastDate, Last(GAD7.Score) AS LastScore
FROM GAD7
GROUP BY GAD7.PatientID
HAVING (((Count(GAD7.PatientID))>=2))
ORDER BY GAD7.PatientID;
Consider:
Query1: Score1
SELECT GAD7.*
FROM GAD7
WHERE 1=(SELECT Count(*)+1 FROM GAD7 AS G7
WHERE G7.PatientID=GAD7.PatientID AND G7.TestDate>GAD7.TestDate);
Query2: Score2
SELECT GAD7.*
FROM GAD7
WHERE 2=(SELECT Count(*)+1 FROM GAD7 AS G7
WHERE G7.PatientID=GAD7.PatientID AND G7.TestDate>GAD7.TestDate);
Query3:
SELECT Score2.PatientID, [Score2].[Score]-[Score1].[Score] AS D
FROM Score1 INNER JOIN Score2 ON Score1.PatientID = Score2.PatientID;
Could nest the SQL statements for an all-in-one query.
Or this all-in-one version using TOP N to pull previous Score:
SELECT GAD7.*, (SELECT TOP 1 Score FROM GAD7 AS Dupe
WHERE Dupe.PatientID = GAD7.PatientID AND Dupe.TestDate<GAD7.TestDate
ORDER BY Dupe.TestDate DESC) AS PrevScore
FROM GAD7 WHERE PatientID IN
(SELECT PatientID FROM GAD7 GROUP BY PatientID HAVING Count(*)>1)
AND 1=(SELECT Count(*)+1 FROM GAD7 AS G7 WHERE G7.PatientID=GAD7.PatientID AND G7.TestDate>GAD7.TestDate);

MS Access Query - Count using most recent inquiries

I am still new to this Access and am not sure how to do this. I have this prospective customer table:
my table and the expected result:
Or here is the data, not sure if it will show correctly:
ID Dates Status
1 12-Sep-15 Follow up
1 2-Jan-15 Request
1 15-Apr-14 Letter
2 1-Sep-15 Request
2 1-Apr-15 Letter
3 12-Dec-15 Follow up
3 11-Sep-14 Request
3 12-Mar-14 Letter
4 14-Jan-16 Letter
4 12-Dec-15 Email
5 12-Jan-16 Letter
5 1 Des 2015 Email
And the result would be like this:
Follow up 2
Request 1
Letter 2
I first tried this SQL:
SELECT id, status, Max(dates) AS TEST
FROM Sample
GROUP BY id, status;
which still would give me the original table. I was hoping it would return the id and status for most recent dates.
Any help would be deeply appreciated. Thank you very much !!
If you want id and status for the latest date, then you need to use a subselect to get the max dates by id and join your table on it by id and date:
SELECT s.id, s.status, t.maxdate
FROM status as s
INNER JOIN
(SELECT id, Max(dates) AS maxdate
FROM Sample
GROUP BY id) as t ON t.id=s.id and t.maxdate=s.dates

Only joining rows where the date is less than the max date in another field

Let's say I have two tables. One table containing employee information and the days that employee was given a promotion:
Emp_ID Promo_Date
1 07/01/2012
1 07/01/2013
2 07/19/2012
2 07/19/2013
3 08/21/2012
3 08/21/2013
And another table with every day employees closed a sale:
Emp_ID Sale_Date
1 06/12/2013
1 06/30/2013
1 07/15/2013
2 06/15/2013
2 06/17/2013
2 08/01/2013
3 07/31/2013
3 09/01/2013
I want to join the two tables so that I only include sales dates that are less than the maximum promotion date. So the result would look something like this
Emp_ID Sale_Date Promo_Date
1 06/12/2013 07/01/2012
1 06/30/2013 07/01/2012
1 06/12/2013 07/01/2013
1 06/30/2013 07/01/2013
And so on for the rest of the Emp_IDs. I tried doing this using a left join, something to the effect of
left join SalesTable on PromoTable.EmpID = SalesTable.EmpID and Sale_Date
< max(Promo_Date) over (partition by Emp_ID)
But apparently I can't use aggregates in joins, and I already know that I can't use them in the where statement either. I don't know how else to proceed with this.
The maximum promotion date is:
select emp_id, max(promo_date)
from promotions
group by emp_id;
There are various ways to get the sales before that date, but here is one way:
select s.*
from sales s
where s.sales_date < (select max(promo_date)
from promotions p
where p.emp_id = s.emp_id
);
Gordon's answer is right on! Alternatively, you could also do a inner join to a subquery to achieve your desired output like this:
SELECT s.emp_id
,s.sales_date
,t.promo_date
FROM sales s
INNER JOIN (
SELECT emp_id
,max(promo_date) AS promo_date
FROM promotions
GROUP BY emp_id
) t ON s.emp_id = t.emp_id
AND s.sales_date < t.promo_date;
SQL Fiddle Demo

Eliminate NULL records in distinct select statement

In SQL SERVER 2008
Relation : Employee
empid clock-in clock-out date Cmpid
1 10 11 17-06-2015 001
1 11 12 17-06-2015 NULL
1 12 1 NULL 001
2 10 11 NULL 002
2 11 12 NULL 002
I need to populate table temp :
insert into temp
select distinct empid,date from employee
This gives all
3 records since they are distinct but what
I need is
empid date CMPID
1 17-06-2015 001
2 NULL 002
Depending on the size and scope of your table, it might just be more prudent to add
WHERE columnName is not null AND columnName2 is not null to the end of your query.
Null is different from other date value. If you wont exclude null record you have to add a and condition like table.filed is not null.
It sounds like what you want is a result table containing a row or tuple (relational databases don't have records) for every employee with a date column showing the date on which the worked or null if they didn't work. Right?
Something like this should do you:
select e.employee_id
from ( select distinct
empid
from employee
) master
left join employee detail on detail.empid = master.empid
and detail.date is not null
The master virtual table gives you the set of destinct employees; the detail gives you employees with non-null dates on which they worked. The left join gives you everything from master with any matches from detail blended in.
Rows in master with no matching rows in details, are returned once with the contributing columns from detail set to null. Rows in master with matching rows in detailare repeated once for each such match, with the detail columns reflecting the matching row's values.
This will give you the lowest date or null for each empid
SELECT empid,
MIN(date) date,
MIN(cmpid) cmpid
FROM employee
GROUP BY empid
try this
select distinct empid,date from employee where date is not null

Find duplicates within a specific period

I have a table with the following structure
ID Person LOG_TIME
-----------------------------------
1 1 2012-05-21 13:03:11.550
2 1 2012-05-22 13:09:37.050 <--- this is duplicate
3 1 2012-05-28 13:09:37.183
4 2 2012-05-20 15:09:37.230
5 2 2012-05-22 13:03:11.990 <--- this is duplicate
6 2 2012-05-24 04:04:13.222 <--- this is duplicate
7 2 2012-05-29 11:09:37.240
I have some application job that fills this table with data.
There is a business rule that each person should have only 1 record in every 7 days.
From the above example, records # 2,5 and 6 are considered duplicates while 1,3,4 and 7 are OK.
I want to have a SQL query that checks if there are records for the same person in less than 7 days.
;WITH cte AS
(
SELECT ID, Person, LOG_TIME,
DATEDIFF(d, MIN(LOG_TIME) OVER (PARTITION BY Person), LOG_TIME) AS diff_date
FROM dbo.Log_time
)
SELECT *
FROM cte
WHERE diff_date BETWEEN 1 AND 6
Demo on SQLFiddle
Please see my attempt on SQLFiddle here.
You can use a join based on DATEDIFF() to find records which are logged less than 7 days apart:
WITH TooClose
AS
(
SELECT
a.ID AS BeforeID,
b.ID AS AfterID
FROM
Log a
INNER JOIN Log b ON a.Person = b.Person
AND a.LOG_TIME < b.LOG_TIME
AND DATEDIFF(DAY, a.LOG_TIME, b.LOG_TIME) < 7
)
However, this will include records which you don't consider "duplicates" (for instance, ID 3, because it is too close to ID 2). From what you've said, I'm inferring that a record isn't a "duplicate" if the record it is too close to is itself a "duplicate".
So to apply this rule and get the final list of duplicates:
SELECT
AfterID AS ID
FROM
TooClose
WHERE
BeforeID NOT IN (SELECT AfterID FROM TooClose)
Please take a look at this sample.
Reference: SQLFIDDLE
Query:
select person,
datediff(max(log_time),min(log_time)) as diff,
count(log_time)
from pers
group by person
;
select y.person, y.ct
from (
select person,
datediff(max(log_time),min(log_time)) as diff,
count(log_time) as ct
from pers
group by person) as y
where y.ct > 1
and y.diff <= 7
;
PERSON DIFF COUNT(LOG_TIME)
1 1 3
2 8 3
PERSON CT
1 3
declare #Count int
set #count=(
select COUNT(*)
from timeslot
where (( (TimeFrom<#Timefrom and TimeTo >#Timefrom)
or (TimeFrom<#Timeto and TimeTo >#Timeto))
or (TimeFrom=#Timefrom or TimeTo=#Timeto)))