Merging two tables in sql with specific conditions: sql server - sql-server

I have these two datasets:
DF1:
PT_ID
Hospital_ID
Admit_Dt
Discharge_DT
Discharge_ID
001
ABC
01-01-2021
01-03-2021
001,ABC,01-01-2021,01-03-2021
001
ABC
01-10-2021
01-15-2021
001,ABC,01-10-2021,01-15-2021
DF2:
PT_ID
ICU_ID
ICU_Admit_Dt
ICU_Discharge_DT
Service_Code
001
XYZ
01-19-2021
01-19-2021
ICU
Desired:
PT_ID
Hospital_ID
Admit_Dt
Discharge_DT
Discharge_ID
Service_Code
001
ABC
01-01-2021
01-03-2021
001,ABC,01-01-2021,01-03-2021
ICU
001
ABC
01-10-2021
01-15-2021
001,ABC,01-10-2021,01-15-2021
NULL
Details: The first table has information on a patients hospital in-patient visits. The 2nd table has information on whether an inpatient visit led to an ICU visit. I would like to create a third table tracking if patients were admitted to the ICU within 30 days of their in-patient discharge date. In the case above, the patient had 2 in-patient visits (DF1) and both discharges for those visits were within 30 days of their 1 ICU visit (DF2). I would like that ICU visit to only count for one of their initial in-patient visits (it does not matter which one if both are within 30 days).
The code I currently have is this:
select distinct
d.PT_ID,
d.Hospital_ID,
d.Admit_Dt,
d.Discharge_DT,
d.Discharge_ID,
t.Service_Code,
from #df1 d
left join #df2 t
on t.PT_ID = d.PT_ID and t.ICU_Admit_Dt between d.Discharge_DT and
DATEADD(day, 30, d.Discharge_DT)
order by PT_ID
What is currently happening is that the ICU visit is being counted for each of the initial discharges which is leading to an over count: (see below):
Current Output:
PT_ID
Hospital_ID
Admit_Dt
Discharge_DT
Discharge_ID
Service_Code
001
ABC
01-01-2021
01-03-2021
001,ABC,01-01-2021,01-03-2021
ICU
001
ABC
01-10-2021
01-15-2021
001,ABC,01-10-2021,01-15-2021
ICU

Related

T-SQL Grouping Dynamic Date Ranges

Using MS SQL Server 2019
I have a set of recurring donation records. Each have a First Gift Date and a Last Gift Date associated with them. I need to add a GroupedID to these rows so that I can get the full date range for the earliest FirstGiftDate and the oldest LastGiftDate as long as there is not a break of more than 45 days in between the recurring donations.
For example Bob is a long time supporter. His card has expired multiple times and he has always started new gifts within 45 days. All of his gifts need to be given a single grouped ID. On the opposite side June has been donating and her card expires. She doesn't give again for 6 months, but then continues to give after her card expires. The first gift of Junes should get its own "GroupedID" and the second and third should be grouped together.The grouping count should restart with each donor.
My initial attempt was to join the donation table back to itself aliased as D2. This did work to give me an indicator of which ones were within the 45 day mark but I can't wrap my head around how to then link them. My only thought was to use LEAD and LAG to try analyze each scenario and figure out the different combinations of LEAD and LAG values needed to make it catch each different scenario, but that doesn't seem as reliable as scaleable as I'd like it to be.
I appreciate any help anyone can give.
My code:
SELECT #Donation.*, D2.*
FROM #Donation
LEFT JOIN #Donation D2 ON #Donation.RecurringGiftID <> D2.RecurringGiftID
AND #Donation.Donor = D2.Donor
AND ABS(DATEDIFF(DAY, #Donation.FirstGiftDate, D2.LastGiftDate)) < 45
Table structure and sample data:
CREATE TABLE #Donation
(
RecurringGiftID int,
Donor nvarchar(25),
FirstGiftDate date,
LastGiftDate date
)
INSERT INTO #Donation
VALUES (1, 'Bob', '2017-02-15', '2018-07-01'),
(15, 'Bob', '2018-08-05', '2019-04-01'),
(32, 'Bob', '2019-04-15', '2022-06-15'),
(54, 'June', '2015-05-01', '2016-05-01'),
(96, 'June', '2016-12-15', '2018-02-01'),
(120, 'June', '2018-03-04', '2020-07-01')
Desired output:
RecurringGiftId
Donor
FirstGiftDate
LastGiftDate
GroupedID
1
Bob
2017-02-15
2018-07-01
1
15
Bob
2018-08-05
2019-04-01
1
32
Bob
2019-04-15
2022-06-15
1
54
June
2015-05-01
2016-05-01
1
96
June
2016-12-15
2018-02-01
2
120
June
2018-03-04
2020-07-01
2
use LAG() to detect when current row is more than 45 days from previous and perform a cumulative sum to form the required Group ID
select *,
GroupedID = sum(g) over (partition by Donor order by FirstGiftDate)
from
(
select *,
g = case when datediff(day,
lag(LastGiftDate, 1, '19000101') over (partition by Donor
order by FirstGiftDate),
FirstGiftDate)
> 45
then 1
else 0
end
from #Donation
) d

Using Case Statement to match multiple values on single row

I'm and trying to create a view which includes data from multiple tables. Where I am stuck is when trying to use a CASE Statement to return a Yes or No answer. I want to query the entire row and only return the Yes answer if both values match on the single row.
TABLE employees
EmpCode
FirstName
Surname
001
Chris
Kite
002
Mark
Flowers
003
Kate
Aid
TABLE areas
EmpCode
Area
Time
001
1
am
001
1
pm
001
2
pm
002
1
am
003
2
am
My CASE Statement is
CASE
WHEN areas.area = '1' AND areas.time = 'am'
THEN 'Yes'
ELSE 'No'
END AS CanWork
I am expecting to see in the result
EmpCode
CanWork
001
Yes
002
No
003
No
however its returning
EmpCode
Can Work
001
Yes
001
Yes
001
No
002
Yes
003
Yes
Group your areas query by emp_code. Or apply WHERE EXISTS construction. Here's the example.
If I understand correctly, the logic in your current CASE expression just belongs in a WHERE clause:
SELECT EmpCode, FirstName, Surname
FROM areas
WHERE area = '1' AND time = 'am';
Note that if there could be more one matching record for each EmpCode, then use SELECT DISTINCT.

Datediff question (number of days since the last appointment of each patient and the 23/09/2019)

Question
List the first name, last name, gender, and the number of days since the last appointment of each patient and the 23/09/2019. The code written for the question is not quite right (I do not want multiple entries for one patient). Please tell me the right code for the question.
Code source: Microsoft SQL server
Code
Go
Use MedicalPractice
Select Patient.FirstName as Patient_FName, Patient.LastName as Patient_LName,
Patient.Gender as Patient_Gender,
Datediff(day, Appointment.AppDate, '2019-09-23') as
DaysBetween_LAppointmentAnd20190923
From dbo.Patient, dbo.Appointment
Where Appointment.Patient_Ref = Patient.Patient_ID
Go
Appointment input data
AppDate Patient_Ref
2019-09-17 10000
2019-09-17 10001
2019-09-18 10000
2019-09-18 10002
Patient input data
Patient_ID FirstName LastName Gender
10000 Luke Smith male
10001 Jess Fox female
10002 Lily Bay female
Try this:
Select Patient.FirstName as Patient_FName, Patient.LastName as Patient_LName,
Patient.Gender as Patient_Gender,
Datediff(day, Appointment.AppDate, '2019-09-23') as
DaysBetween_LAppointmentAnd20190923
From dbo.Patient,
INNER JOIN (SELECT Appointment.Patient_Ref,MAX(Appointment.AppDate) OVER (PARTITION BY
Appointment.Patient_Ref ORDER BY Appointment.Patient_Ref) AS AppDateFROM
dbo.Appointment) Appointment ON Appointment.Patient_Ref = Patient.Patient_ID
Go

SQL: Combining three tables using JOIN and UNION

In a rental management database I have three tables, one containing my article stock, one for the bookings of those articles and one storing all projects:
stock
IdStockType Number Caption Inventory
1 100001 Monitor 10
2 100002 Keyboard 25
3 100003 Notebook 05
4 100004 Desktop 07
bookings
id IdStockType RentalPrice Factor Project
1 2 15 5 1
2 2 03 2 2
3 4 90 3 2
projects
id Caption startDate endDate
1 Festival 2019 2019-03-01 2019-03-05
2 Kick-Off ABC 2019-04-15 2019-04-17
3 Big Conference 2019-04-16 2019-04-16
Now I want to write a query giving me the whole stock with information about bookings and project. If an article was not rented, it should be listed anyway. If it was rented, it should only be listed with the booking & project information. So it can be there multiple times:
IdStockType Number Factor Inventory Article RentalPrice Project
1 100001 (NULL) 10 Monitor (NULL) (NULL)
2 100002 5 25 Keyboard 15 Festival 2019
2 100002 2 25 Keyboard 03 Kick-Off ABC
3 100003 (NULL) 05 Notebook (NULL) (NULL)
4 100004 3 07 Desktop 90 Kick-Off ABC
Now I have problem with my query:
SELECT * FROM (
SELECT
p.IdStockType,
p.Number,
o.Factor,
p.Inventory,
p.Caption AS Article,
q.Caption AS Project
FROM
stock p,
bookings o,
projects q
WHERE
p.IdStockType = o.IdStockType AND
o.Project = q.id
) AS u
RIGHT JOIN (SELECT
r.IdStockType,
r.Number,
NULL,
NULL,
r.Caption AS Article,
NULL
FROM
stock r) d ON d.IdStockType = u.IdStockType;
The resulting amount of outputted lines seems to be correct, but the combination of the information is weird because the concordant columns are added as new ones.
Can anybody help me with the query?
Thanks in advance.
Regards
Lars
select *
from Stock stock
left join (
select
*
from
Bookings bookings
join Projects projects
on bookings.Project = projects.Id
) bookingProjects on stock.IdStockType = bookingProjects.IdStockType

To Display a Stock Details

I am trying to display the stock details like MRP, Sales Rate , Tax Amount and so on.
I used three grid views to make a entry in my form. They are,
GV Purchase
GV Product Details - (It is used to show the product name and product code )
GV Stock Details - (It is used to show the Quantity, MRP, Sales Price and so on)
I used SQL Query for populate the DB records in my grid view.
I select a Product A from Product Grid view in my form ,the Stock grid will show the corresponding data of the Product A
My DB records,
code Name QTY MRP S.Rate
aa11 Pro A 5 120.00 130.00
aa11 Pro A 2 130.00 150.00
aa12 Pro B 4 100.00 110.00
aa13 Pro C 2 50.00 60.00
When I select Pro A in GV Product Details in my form. The GV Stock Details will be shown the QTY, MRP, S.Rate for the Pro A
But My Query returns like this format
aa11 Pro A 5 120.00 130.00
2 130.00 150.00
4 100.00 110.00
2 50.00 60.00
This is my Query,
select s.*,iif( d.NewSalePrice is null,s.saleprice1,d.NewSalePrice)as NewSalePrice,Pdate from (select s.*,p.ProductFullName,p.ProductCode from Stock s,Product p where s.productfullcode=p.ProductFullCode) s left join(select Productfullcode,MRP,PUnitPrice,NewSalePrice,Pdate from DailyPricing ) d on s.ProductFullCode=d.ProductFullCode where s.MRP=d.MRP and s.UnitPrice=d.PUnitPrice and Pdate=(select MAX(Pdate) from DailyPricing where PUnitPrice=s.UnitPrice and mrp=s.MRP and ProductFullCode=s.ProductFullCode) order by ProductFullCode
How to I get Stock details only matched by Pro A
Note : These table format is just a model for my Table
Thanks in Advance,
Vinayak vk.:-)
You could probably simplify your query, and add a where clause for the product name you need.
Haven't tested it against mock data, but something like this SQL:
select
s.*,
p.ProductFullName,
p.ProductCode,
coalesce(d.NewSalePrice, s.saleprice1) as SalePrice,
max(d.Pdate) over (partition by p.ProductFullCode, s.mrp, s.UnitPrice) as MaxPdate
from Product p
join Stock s on s.productfullcode = p.ProductFullCode
join DailyPricing d on (s.ProductFullCode = d.ProductFullCode and s.MRP = d.MRP and s.UnitPrice = d.PUnitPrice)
where p.ProductFullName = 'Pro A'
order by p.ProductFullCode

Resources