SQL, Update with most recent data info - sql

I have 2 tables shown below:
Table 1
Student ID - DATE_NO - SCORE
Table 2
STUDENT_ID - DATE_NO - HT - WT
Table 1 has the physical test scores and the date of the test for each student while Table 2 lists their height (HT) and weight (WT) and the date they were measured.
Example Data:
Table 1
Student ID | DATE_NO | SCORE |
125 | 3 | 90 |
572 | 6 | 75 |
687 | 11 | 95 |
Table 2
Student_ID | DATE_NO | HT | WT |
125 | 2 | 70 | 150 |
125 | 3 | 72 | 155 |
125 | 6 | 72 | 160 |
572 | 2 | 70 | 200 |
572 | 5 | 70 | 225 |
572 | 8 | 70 | 215 |
572 | 9 | 70 | 220 |
687 | 4 | 65 | 140 |
687 | 7 | 67 | 150 |
687 | 11 | 70 | 155 |
687 | 12 | 67 | 160 |
I am not guaranteed to have the exact same DATE_NO for both HT/WT and the Test score date. I want the most recent HT and WT for each student when they took their physical test. Based on the example data above, the optimal join would give me the table below:
Modified Table 1
Student ID | DATE_NO | HT | WT |
125 | 3 | 72 | 155 |
572 | 6 | 70 | 225 |
687 | 11 | 70 | 155 |
I'd like to use the UPDATE statement on Table 1, so after altering Table 1 with HT int and WT int, I attempt to do the following:
UPDATE T1
SET HT = T2.HT, WT = T2.WT
FROM Table_1 as T1
INNER JOIN Table_2 AS T2 ON T1.STUDENT_ID = T2.STUDENT_ID
WHERE (T1.DATE_NO) >= (T2.DATE_NO)
But the result gives me the FIRST record that meets the criteria. Switching greater than to less than [ >= to <= ] Make the HT/WT for each student the entries for Month 6,8, and 12) when it should be month 3,8, and 11. Any suggestions?
FYI: Won't be able to apply any solutions till Friday.

Is it something like this you're looking for:
UPDATE Q
SET
T1_HT = T2_HT
, T1_WT = T2_WT
FROM
(
SELECT
T1.HT T1_HT
, T1.WT T1_WT
, T2.HT T2_HT
, T2.WT T2_WT
, ROW_NUMBER() OVER (PARTITION BY T1.STUDENT_ID ORDER BY T2.DATE_NO DESC) R
FROM
Table_1 T1
JOIN Table_2 T2 ON
T1.STUDENT_ID = T2.STUDENT_ID
AND T2.DATE_NO <= T1.DATE_NO
) Q
WHERE R = 1

SELECT ts.student_id,
ts.date_no,
hw.ht,
hw.wt
FROM test_scores ts,
ht_wt hw
WHERE hw.student_id = ts.student_id
AND hw.date_no <= ts.date_no
AND hw.date_no =
(SELECT max(date_no)
FROM ht_wt
WHERE date_no <= ts.date_no
AND student_id = ts.student_id)
sql fiddle here

Related

sql join with multiple conditions on columns

I don't think I can achieve this with unions.
For example, I want all cars where the key-column is "brand" and value-column is "Burago".
On top of that, the key-column price with values between 100 and 220.
Should I do subqueries or something? What if I want to query the key "type" with value "sport" too?
The query only returns something when I use one where clause and returns nothing when use the following query.
select `posts`.`title` from `posts`
inner join `meta` on `posts`.`id` = `meta`.`metable_id`
where `meta`.`key` = "price" and `meta`.`value` between 100 and 220
and `meta`.`key` = "brand" and `meta`.`value` = "Burago"
group by `posts`.`id`
The meta table:
ID | post_id | key | value
----------------------------------------------------
69 | 8 | brand | some-brand
----------------------------------------------------
70 | 8 | type | sport
----------------------------------------------------
70 | 8 | price | 100
----------------------------------------------------
71 | 8 | brand | some-other-brand
----------------------------------------------------
70 | 8 | type | coupe
----------------------------------------------------
72 | 8 | price | 150
----------------------------------------------------
73 | 8 | brand | some-brand
----------------------------------------------------
70 | 8 | type | cabrio
----------------------------------------------------
74 | 8 | price | 100
----------------------------------------------------
75 | 8 | brand | some-brand
----------------------------------------------------
70 | 8 | type | sport
----------------------------------------------------
76 | 8 | price | 250
select `posts`.`title` from `posts`
inner join `meta` on `posts`.`id` = `meta`.`metable_id`
where `meta`.`key` = "price" and `meta`.`value` between 100 and 220
and `meta`.`key` = "brand" and `meta`.`value` = "Burago"
group by `posts`.`id`
having COUNT(DISTINCT `meta`.`key`) = 2

SQL Server: Count with conditions

I have a table which follows the state of the item delivery:
ID | ContractID | State
----------------------------------
1 | 125 | Created
2 | 125 | Activated
3 | 125 | PickupStarted
4 | 125 | PickedUp
5 | 125 | DeliveryStarted
6 | 125 | Delivered
7 | 126 | Created
8 | 126 | Activated
9 | 126 | PickupStarted
10 | 126 | PickedUp
11 | 126 | DeliveryStarted
12 | 126 | Delivered
13 | 127 | Created
14 | 127 | Activated
15 | 127 | PickupStarted
16 | 127 | PickedUp
I would like to create SQL query which counts only those 'ContractIds' which are not delivered yet (only those whose current status has reached 'PickedUp' status). In this case that would be 'ContractId' 127.
Is there a way to do that type of COUNT()?
You can use not exists:
select count(distinct contractId)
from t
where not exists (select 1
from t t2
where t2.contractId = t.contractid and
t2.status not like 'Deliver%'
);
Or, if you specifically want to get PickedUp as the last status:
select count(*)
from t
where t.id = (select max(t2.id) from t t2 2here t2.contractid = t.contractid) and
t.status = 'PickedUp';
The two are different. The second is specifically that the last status is PickedUp. The first is anyone that has not reached a "deliver" status.

SQL server 2008: join 3 tables and select last entered record from child table against each parent record

I have following 3 tables and last entered reasoncode from Reasons table against each claimno in claims table.
Reasons:
Rid |chargeid| enterydate user reasoncode
-----|--------|-------------|--------|----------
1 | 210 | 04/03/2018 | john | 99
2 | 212 | 05/03/2018 | juliet | 24
5 | 212 | 26/12/2018 | umar | 55
3 | 212 | 07/03/2018 | borat | 30
4 | 211 | 03/03/2018 | Juliet | 20
6 | 213 | 03/03/2018 | borat | 50
7 | 213 | 24/12/2018 | umer | 60
8 | 214 | 01/01/2019 | john | 70
Charges:
chargeid |claim# | amount
---------|-------|---------
210 | 1 | 10
211 | 1 | 24.2
212 | 2 | 5.45
213 | 2 | 76.30
214 | 1 | 2.10
Claims:
claimno | Code | Code
--------|-------|------
1 | AH22 | AH22
2 | BB32 | BB32
Expected result would be like this:
claimno | enterydate | user | reasoncode
--------|-------------|--------|-----------
1 | 01/01/2019 | john | 70
2 | 26/12/2018 | umer | 55
I have applied many solutions but no luck. Following is the latest solution I was trying using SQL Server 2008 but still got incorrect result.
With x As
(
select r.chargeid,r.enterydate,ch.claimno from charges ch
join (select chargeid,max(enterydate) enterydate,user from Reasons group by chargeid) r on r.chargeid = ch.chargeid
)
select x.*,r1.user, r1.reasoncode from x
left outer join Reasons r1 on r1.chargeid = x.chargeid and r1.enterydate = x.enterydate
--group by x.claimno
Is this what you want?
select claimno, enterydate, user, reasoncode
from (select c.claimno, r.*,
row_number() over (partition by c.claimno order by r.entrydate desc) as seqnum
from charges c join
reasons r
on c.chargeid = r.chargeid
) cr
where seqnum = 1;
You can try using row_number()
select * from
(
select r.chargeid,r.enterydate,ch.claimno,user,reasoncode,
row_number() over(partition by ch.claimno order by r1.enterydate desc) as rn
from charges ch left outer join Reasons r1 on r1.chargeid = ch.chargeid
)A where rn=1

show duplicate rows in access

i have this table
MEN
id | Qty | Place
========================
111 | 10 | 55
111 | 20 | 66
111 | 10 | 77
222 | 40 | 11
333 | 50 | 11
111 | 10 | 22
222 | 44 | 33
222 | 40 | 44
333 | 15 | 55
i need to show all the records that id=id and Qty=Qty like this:
id | Qty | Place
=====================
111 | 10 | 55
111 | 10 | 77
111 | 10 | 22
222 | 40 | 11
222 | 40 | 44
You can do something like this:
SELECT MEN.Id, MEN.Qty, MEN.Place
FROM MEN INNER JOIN
(SELECT MEN.Id, MEN.Qty
FROM MEN
GROUP BY MEN.Id, MEN.Qty
HAVING (((Count(*))>1))) AS a
ON (MEN.Qty = a.Qty) AND (MEN.Id = a.Id)
ORDER BY MEN.Id, MEN.Qty;
Create the inner query to find where there are more than one instances of the Id then join it back to the original table to get the Place values.
Try this
SELECT T.ID,T.Qty
FROM Table1 T
GROUP BY T.ID,T.Qty
HAVING (((Count(*))>1));
Use Below query to get full set of record details:
SELECT R.Id, R.Qty, R.Place
FROM Table1 R INNER JOIN
(
SELECT T.Id, T.Qty
FROM Table1 T
GROUP BY T.Id, T.Qty
HAVING (((Count(*))>1))
)AS JR ON R.Qty = JR.Qty AND R.Id = JR.Id

SQL Server 2008 - accumulating column

I would like to accumulate my data as you can see below there is origin table table1:
What is the best query for to do this?
Is possible to do this dynamically - when I add more types of terms??
Table 1
ID | term | value
-----------------------
1 | I | 100
2 | I | 200
3 | II | 100
4 | II | 50
5 | II | 75
6 | III | 50
7 | III | 65
8 | IV | 30
9 | IV | 45
And the result should be like below:
YTD | Acc Value
------------------
I-I | 300
I-II | 525
I-III| 640
I-IV | 715
Thanks
select
(select min(term) from yourtable ) +'-'+term,
(select sum(value) from yourtable t1 where t1.term<=t.term)
from yourtable t
group by term