I want to display only the most recent appointmentId by CustomerId . I know im doing the query all wrong but how can i achieve the desired result
SELECT TEMP.AppointmentId,TEMP.AppointmentDateTime,TEMP.PatientId,MAX(TEMP.AppointmentDateTime)
FROM
(SELECT
Appointment.Id AS AppointmentId,
Appointment.DateTime AS AppointmentDateTime,
Customer.Id AS CustomerId
FROM Customer
INNER JOIN Appointment ON Appointment.CustomerId = Customer.Id
INNER JOIN CustomerUser ON CustomerUser.CustomerId = Customer.Id
WHERE Appointment.UpdatedAt >= #StartDate AND Appointment.UpdatedAt <= #EndDate
AND Appointment.Is_Active = 1
AND Customer.Is_Active = 1
AND CustomerUser.Is_Active = 1
) AS TEMP
GROUP BY TEMP.AppointmentId,TEMP.AppointmentDateTime,TEMP.CustomerId
This is the result set that i have
AppointmentId AppointmentDateTime CustomerId
8909 2020-12-24 13:39:00 98
8931 2020-12-18 10:30:00 26
8932 2020-12-17 14:30:00 26
8933 2020-11-06 15:30:00 26
8934 2020-12-30 17:31:00 153
8936 2020-12-21 11:06:00 180
8938 2020-12-25 23:00:00 153
8943 2020-12-21 17:45:00 188
9046 2020-12-30 13:49:00 98
But this is the Expected result
AppointmentId AppointmentDateTime CustomerId
8931 2020-12-18 10:30:00 26
8934 2020-12-30 17:31:00 153
8936 2020-12-21 11:06:00 180
8943 2020-12-21 17:45:00 188
9046 2020-12-30 13:49:00 98
I want to display only the most recent appointmentId of a Patient based on the AppointmentDateTime.
One method is a correlated subquery:
select a.*
from Appointment a
where a.AppointmentDateTime = (select max(a2 AppointmentDateTime)
from Appointment a2
where a2.customerid = a.customerid
);
Your query is considerably more complicated than this, including tables and conditions not explained in the question. However, this answers the question that you have asked.
You made it too complicated. You only need one query and you need to remove your aggregated field from the group by statement.
SELECT
MAX(Appointment.Id) AS MaxAppointmentId,
MAX(Appointment.DateTime) AS AppointmentDateTime,
Customer.Id AS CustomerId
FROM Customer
INNER JOIN Appointment ON Appointment.CustomerId = Customer.Id
INNER JOIN CustomerUser ON CustomerUser.CustomerId = Customer.Id
WHERE Appointment.UpdatedAt >= #StartDate AND Appointment.UpdatedAt <= #EndDate
AND Appointment.Is_Active = 1
AND Customer.Is_Active = 1
AND CustomerUser.Is_Active = 1
GROUP BY Customer.Id
I think this will do what you want.
select *
from
( select *, row_number() over (partition by customerid order by AppointmentDateTime desc) as rn
from expandtable ) as t
where rn = 1
Related
Need some help please.
I have the following table:
Accountno
TrackNo
PercentInc
CreateDate
Lastdate
123456
396
3
01/03/2019
24/05/2021
123456
516
0.9
20/01/2020
25/06/2020
123456
516
3
01/07/2013
29/10/2021
123456
396
1
12/12/2018
12/05/2018
123456
396
2
05/09/2019
08/11/2019
123456
516
0.4
08/09/2018
30/12/2020
I need to show results one row per TrackNo - I have to display the PercentInc where the CreateDate is the latest but show the LastDate for that row with the max (LastDate)
Results:
Accountno
TrackNo
PercentInc
CreateDate
Lastdate
123456
396
2
05/09/2019
24/05/2021
123456
516
0.9
20/01/2020
29/10/2021
Thanks
You can use window functions:
select Accountno, TrackNo, PercentInc, CreateDate, max_Lastdate
from (select t.*,
row_number() over (partition by accountno, trackno order by createdate desc) as seqnum,
max(lastdate) over (partition by accountno, trackno) as max_lastdate
from t
) t
where seqnum = 1;
There are many ways to skin a cat with SQL. One approach that I find intuitive:
Get the maximum dates for each TrackNo from a query like this:
SELECT TrackNo, MAX(CreateDate) MaxCreateDate, MAX(Lastdate) MaxLastDate
FROM Table
GROUP BY TrackNo
Then link this to the two records you want with a sub-query and two inner joins:
SELECT maxLastDate.Accountno, maxCreateDate.TrackNo, maxCreateDate.PercentInc, maxCreateDate.CreateDate, maxLastDate.Lastdate
FROM (
SELECT TrackNo, MAX(CreateDate) MaxCreateDate, MAX(Lastdate) MaxLastDate
FROM Table
GROUP BY TrackNo
) AS maxDates
INNER JOIN Table AS maxCreateDate
ON maxCreateDate.TrackNo = maxDates.TrackNo AND maxCreateDate.CreateDate = maxDates.MaxCreateDate
INNER JOIN Table AS maxLastDate
ON maxLastDate.TrackNo = maxDates.TrackNo AND maxLastDate.Lastdate = maxDates.MaxLastDate
I have a table EmployeeContract similar like this:
ContractId
EmployeeId
ValidFrom
ValidTo
Salary
12
5
2018-02-01
2019-06-31
x
25
8
2015-01-01
2099-12-31
x
50
5
2019-07-01
2021-05-31
x
52
6
2011-08-01
2021-12-31
x
72
8
2010-08-01
2014-12-31
x
52
6
2011-08-01
2021-12-31
x
Table includes history contracts in company for each employee. I need to get date when employees started work and last date of contract. Sometime records has duplicates.
For example, based on data from above:
EmployeeId
ValidFrom
ValidTo
5
2018-02-01
2021-05-31
8
2010-08-01
2099-12-31
6
2011-08-01
2021-12-31
Base on this article: https://www.techcoil.com/blog/sql-statement-for-selecting-the-latest-record-in-each-group/
I prepared query like this:
select minv.*, maxv.maxvalidto from
(select distinct con.[EmployeeId], mvt.maxvalidto
from [EmployeeContract] con
join (select [EmployeeId], max(validto) as maxvalidto
FROM [EmployeeContract]
group by [EmployeeId]) mvt
on con.[EmployeeId] = mvt.[EmployeeId] and mvt.maxvalidto = con.validto) maxv
join
(select distinct con.[EmployeeId], mvf.minvalidfrom
from [EmployeeContract] con
join (select [EmployeeId], min(validfrom) as minvalidfrom
FROM [EmployeeContract]
group by [EmployeeId]) mvf
on con.[EmployeeId] = mvf.[EmployeeId] and mvf.minvalidfrom = con.validfrom) minv
on minv.[EmployeeId] = maxv.[EmployeeId]
order by 1
But I'm not satisfied, i think it's not easy to read, and probably optimize is poor. How can I do it better?
I think you want group by:
select employeeid, min(validfrom), max(validto)
from employeecontract
group by employeeid
Hi I would like to make a select expression using case or if/else which seems to be a simple solution from logic perspective but I can't seem to get it to work. Basically I am joining against two table here, the first table is customer record with date filter called min_del_date and then the second table for the model scoring table with BIN and update_date parameters.
There are two logics I want to display
Picking the model score that was the month before min_del_date
If model score month before delivery is greater than 50 (Bin > 50) then pick the model score for same month as min_del_date
My 1st logic code is below
with cust as (
select
distinct cust_no, max(del_date) as del_date, min(del_date) as min_del_date, (EXTRACT(YEAR FROM min(del_date)) -1900)*12 + EXTRACT(MONTH FROM min(del_date)) AS upd_seq
from customer.cust_history
group by 1
)
,model as (
select party_id, model_id, update_date, upd_seq, bin, var_data8, var_data2
from
(
select
party_id, update_date, bin, var_data8, var_data2,
(EXTRACT(YEAR FROM UPDATE_DATE) -1900)*12 + EXTRACT(MONTH FROM UPDATE_DATE) AS upd_seq,
dense_Rank() over (partition by (EXTRACT(YEAR FROM UPDATE_DATE) -1900)*12 + EXTRACT(MONTH FROM UPDATE_DATE) order by update_date desc) as rank1
from
(
select party_id,update_date, bin, var_data8, var_data2
from model.rpm_model
group by party_id,update_date, bin, var_data8, var_data2
) model
)model_final
where rank1 = 1
)
-- Add model scores
-- 1st logic Picking the model score that was the month before delivery date
select *
from
(
select cust.cust_no, cust.del_date, cust.min_del_date, model.upd_seq, model.bin
from cust
left join cust
on cust.cust_no = model.party_id
and cust.upd_seq = model.upd_seq + 1
)a
Now I am struggling in creating the 2nd logic in the same query?.. any assistance would be appreciated
cust table
cust_no
min_del_date
upd_seq
123
2021-01-11
1453
234
2020-06-29
1446
456
2020-07-20
1447
model table
party_id
update_date
upd_seq
BIN
123
2020-11-30
1451
22
123
2020-12-25
1452
54
123
2020-01-11
1453
14
234
2020-05-23
1445
76
234
2020-06-18
1446
48
234
2020-07-23
1447
12
456
2020-06-18
1446
23
456
2020-07-23
1447
39
456
2020-08-21
1448
21
desired results
cust_no
min_del_date
model.upd_seq
update_date
BIN
123
2021-01-11
1453
2020-01-11
14
234
2020-06-29
1446
2020-06-18
48
456
2020-07-20
1446
2020-06-18
23
Update
I managed to find the solution by myself, thanks for everyone who has attending this question. The solution is per below
select a.cust_no, a.del_date, a.min_del_date, b.update_date, b.upd_seq, b.bin
from
(
select cust.cust_no, cust.del_date, cust.min_del_date,
CASE WHEN model.BIN <=50 THEN model.upd_seq WHEN BIN > 50 THEN model.upd_seq +1 ELSE NULL END as upd_seq
from cust
inner join model
on cust.cust_no = model.party_id
and cust.upd_seq = model.upd_seq + 1
)a
inner join model b
on a.cust_no = b.party_id
and a.upd_seq = b.upd_seq
I have 3 tables in a Postgres 9.5 DB like below,
threshold
id threshold_amount
----------------------
111 100
112 200
113 80
customers - each customer has a threshold_id of threshold table
id customer_name threshold_id
--------------------------------
313 abc 111
314 xyz 112
315 pqr 113
charges - per customer there is charges so this table has customer_id
id customer_id amount post_date
------------------------------------
211 313 50 4/1/2017
212 313 50 4/30/2017
213 313 50 5/15/2017
214 314 100 3/1/2017
215 314 50 3/21/2017
216 314 50 4/21/2017
217 314 100 5/1/2017
218 315 80 5/5/2017
I want to query it and return the specific post_date with sum( amount ) == threshold_amount by ascending order of charges.id column,
The resultset look like below,
customer_id post_date
-----------------------
313 4/30/2017
314 4/21/2017
315 5/5/2017
I've tried sum( amount ) with group by customer_id and call the one separate the stored procedure from select clause and pass the amount, post_date and threshold_amount then created one temp table and insert post_date into it if the above condition get match and then again access that temp table but it seems something not valid so I want to know if some other solution or Can I do it in query?
Thanks
Your question is asking about an exact match for the threshold. This is basically a cumulative sum:
select cct.*
from (select ch.customer_id, ch.amount,
sum(ch.amount) over (partition by ch.customer_id order by post_date) as running_amount,
t.threshold_amount
from charges ch join
customers c
on ch.customer_id = c.id join
threshholds t
on c.threshold_id = t.id
) cct
where running_amount = threshold_amount;
try this:
select
c.customer_id,
c.post_date
from charges c
join customers cu on cu.id = c.customer_id
join threshold t on t.id = cu.threshold_id
where (select sum(cc.amount) from charges cc where cc.id <= c.id
and cc.customer_id = c.customer_id) = t.threshold_amount
I have two queries that work perfectly.
SELECT fy.date_stop as pend
FROM account_fiscalyear fy
WHERE <any date> BETWEEN fy.date_start AND fy.date_stop
This returns the last date of the fiscal year in which can be found.
and
SELECT a.id as id, COALESCE(MAX(l.date),a.purchase_date) AS date
FROM account_asset_asset a
LEFT JOIN account_move_line l ON (l.asset_id = a.id)
WHERE a.id <some condition>
GROUP BY a.id, a.purchase_date
This returns a results similar to the following giving the asset id and purchase date or last depreciation date for the asset.
61 2014-09-01
96 2014-09-01
115 2015-02-25
181 2015-11-27
122 2015-04-03
87 2014-09-01
67 2014-09-01
207 2016-09-09
54 2014-09-01
159 2015-08-25
163 2015-08-19
....
The result I want is the asset id but this time with the last day of the financial year that the purchase date or last depreciation date can be found in. I just don't seem to be able to find a way to combine the two queries.
Solved it.
SELECT a.id as id, COALESCE(MAX(l.date), a.purchase_date) as date
FROM
(SELECT ass.id as id, fy.date_stop as purchase_date
FROM account_fiscalyear fy, account_asset_asset ass
WHERE ass.purchase_date BETWEEN fy.date_start AND fy.date_stop) a
LEFT JOIN
(SELECT mvl.asset_id as asset_id, fy.date_stop as date
FROM account_move_line mvl, account_period per, account_fiscalyear fy
WHERE mvl.period_id = per.id AND per.fiscalyear_id = fy.id) l
ON (l.asset_id = a.id)
GROUP BY a.id, a.purchase_date