SQL Code to Update Entities with the same ID - sql

We have an app to manage our Member's information that is tied to a SQL Database. We have attributes that the users can set that apply to the whole family. I am trying to write a SQL Script that will update the values for the whole family.
Example:
Here is a sample of a few columns of our dbo.AttributeValue column:
AttributeID
EntityID
Value
CreatedDateTime
ModifiedDateTime
5856
733
True
2021-11-06 17:30:38.207
2021-11-10 13:52:09.843
5856
613
Fale
2021-11-05 12:12:08.207
2021-11-16 3:32:01.843
Here is a sample of a few columns in our dbo.Person Table:
ID
PrimaryFamilyID
733
187
709
187
137
187
I would like for anyone with the same value in PrimaryFamilyID to have the same values in the dbo.AttributeValue table. Bonus points if we can make it update to the value with the most recent ModifiedDateTime in the dbo.AttributeValue table so that if someone in the family modifies the value after every has an assigned attribute, it will go ahead an update those as well.
Desired outcome:
AttributeID
EntityID
Value
CreatedDateTime
ModifiedDateTime
5856
733
True
2021-11-06 17:30:38.207
2021-11-10 13:52:09.843
5856
709
True
2021-11-06 17:30:38.207
2021-11-10 13:52:09.843
5856
137
True
2021-11-06 17:30:38.207
2021-11-10 13:52:09.843

It took me a while to get to a solution what you want is but here it is
DBFiddleRunningSolution
You can start somewhere from here.
With PersonCTE as (
Select Count(*) as cnt,PrimaryFamilyId
from Person
group by PrimaryFamilyId
having count(*)>1
)
Select AV.AttributeId,P.Id,AV.Value,AV.CreatedDateTime,AV.ModifiedDateTime
into NewAttributeValue
from Person P inner join PersonCTE C
ON P.PrimaryFamilyId = C.PrimaryFamilyId
cross join AttributeValue AV
where AV.EntityId in (Select distinct Id from Person)

Related

Select from Multiple tables using Where, Max and SUM functions

I'm trying to get the following results,
based on my current WHERE statement I get several records which are from the same project_id, I'm interested in the latest based on id
from the second table I get multiple rows due to amount field, this could have several entries some additive or deductive. I would like to sum this amount and separate the deductive and additive
all of these resulst I want grouped by project_id so that I only have one row for each project_id
Table uco1
project_id
OrigProjName_TB
status
id
Table ucoline
record_id
amount
SELECT
a.project_id,
a.OrigProjName_TB,
a.CO_NewContract_CA,
a.con_amount_ca,
a.co_changeorderdate_do,
a.co_changeid_tb,
a.co_thiscoamount_ca,
a.OrigProjID_TB,
a.PIF_SpecNumber_TB,
a.CO_TITLE_TB,
a.status,
b.amount
FROM unifier_uco1 a
LEFT JOIN unifier_uco1_lineitem b
ON a.id = b.record_id
WHERE a.status = 'Authorized' OR a.status = 'Ratified'
What I have so far is this...
project_id
OrigProjName_tb
status
id
record_id
amount
2103
demo2
Authorized
786
786
142418
2103
demo2
Authorized
832
832
-523961
2103
demo2
Authorized
784
784
458228
2103
demo2
Authorized
784
784
67565
2100
demo3
Ratified
774
774
-852.85
2100
demo3
Ratified
774
774
4557
What I would like to see is the following;
project_id
OrigProjName_tb
status
id
record_id
additive
deductive
2103
demo2
Authorized
832
832
-523961
2100
demo3
Ratified
774
774
4557
-852.85
unfortunately for me I'm very new at this and just know a couple of basic functions. I even tried creating separate tables with basic functions to try and split up each function and later try to join all into one. This also resulted in a mess since I'm not familiar with all the different functions and statements.
I appreciate your help in advance and also, if you can provide best place to learn I would greatly appreciate that as well.
Thanks,

Including variables after filtering selecting only minimum values in SQL?

I am working with a twin dataset and would like to create a table with the Subject ID (Subject) and twin pair ID (twpair) for the twins with the lower (or one of the twins if the values are equal) lifetime total of marijuana use (MJ1a).
A portion of my table looks like this:
Subject
twpair
MJ1a
156
345
10
157
345
7
158
346
20
159
346
3
160
347
4
161
347
4
I'm hoping to create a table with only the twins that have the lower amount of marijuana use which would look like this:
Subject
twpair
MJ1a
157
345
7
159
346
3
161
347
4
This is the SQL code I have so far:
proc sql;
create table one_twin as
select twpair,min(MJ1a) as minUse, Subject
from twins_deviation
group by twpair;
Unfortunately this ends up causing all of the subjects to be remerged back in the dataset. If I don't include the Subject portion I get the correct values for twpair and MJ1a but not the Subject IDs.
How do I filter the dataset to only include those with the minimum values while also including variables of interest like Subject ID? Note that if two pairs of twins have the SAME value I would like to select one but it doesn't matter which I select. Any tips would be extremely appreciated!
This query should give you the desired result.
select a.subject,a.twpair,a.MJ1a from twins_deviation a join (select twpair,min(mj1a) as mj1a from twins_deviation group by twpair)b on a.twpair=b.twpair and a.mj1a=b.mj1a
If your DB supports analytic/window functions ,the same can be accomplished using a rank function ,solution given below.
EDIT1:to handle same values for mj1a
select subject,twpair,mj1a from(select subject,twpair,mj1a ,row_number() over(partition by twpair order by mj1a) as rnk from twins_deviation)out1 where rnk=1;
EDIT2:Updated solution 1 to include only one twin.
select min(subject) as subject,twpair,mj1a from(select a.subject as subject ,a.twpair as twpair,a.MJ1a as MJ1a from twins_deviation a join (select twpair,min(mj1a) as mj1a from twins_deviation group by twpair)b on a.twpair=b.twpair and a.mj1a=b.mj1a)out1 group by twpair,MJ1a;

Join tables where no common field exists and based on ID columns

This question seems hard to phrase, but after explaining my situation it should be easy to understand. I have two tables: one called INSTRUCTORS that holds instructor data and another called LIST_OPTION_ITEM that holds the ID values of different ID columns stored in the INSTRUCTORS table. A third and possibly important table to include is LIST_OPTION_TYPE, which contains the IDs of whatever ID column there is in INSTRUCTORS. Perhaps it would be easier to explain by showing sample data and my desired output.
INSTRUCTORS
RANK_ID
SPECIALTY_ID
DUTY_TITLE_ID
SERVICE_BRANCH_ID
STATUS_ID
UNIT_ID
OFFICE_SYMBOL_ID
1354
319
931
2604
1378
1406
1429
LIST_OPTION_ITEM
OPTION_ITEM_ID
OPTION_TYPE_ID
ITEM_VALUE
1354
22
CAPT
319
20
CBRN TRAUMA NURSE
931
21
IDMT-Squadron Medical Element
2604
128
46N NURSE
1378
23
USA
1406
24
Guard
1429
126
CERFP
LIST_OPTION_TYPE
OPTION_TYPE_ID
OPTION_TYPE
20
Specialty
21
Duty_Title
22
Rank
23
Service_Branch
24
Status
126
Unit
128
Office_Symbol
It is important to note that I cannot join INSTRUCTORS and LIST_OPTION_ITEM, as there is no common column. However, LIST_OPTION_ITEM and LIST_OPTION_TYPE can join on OPTION_TYPE_ID. My desired output from a SELECT query:
Rank
Specialty
Duty Title
Service Branch
Status
Unit
Office Symbol
CAPT
CBRN TRAUMA NURSE
IDMT-Squadron Medical Element
46N NURSE
USA
Guard
CERFP
I've tried some solutions but can't come up with anything. Do I need a cross join or something? Help would be much appreciated.
I tried to do with Pivot and unpivot functions
below is sample sql:
with inst as (select inst_id, col, col_id
from (select rownum as inst_id, a.* from instructor a)
unpivot
(col_id for col in (status_id as 'STATUS',rank_id as 'RANK',specialty_id as 'SPECIALTY',duty_title_id as 'DUTY_TITLE')
))
select * from
(select inst_id,col,item_value from inst,
(select a.option_type,b.option_item_id,b.item_value from LIST_OPTION_TYPE a, list_option_id b
where a.option_type_id = b.option_type_id) opt
where inst.col = upper(option_type)
and option_item_id = col_id)
pivot
(max(item_value)
for col in ('STATUS','RANK','SPECIALTY','DUTY_TITLE')
) order by inst_id;
this will give desired output

How to get the set size, first and last record in a db2 ordered set with one call

I have a very big transaction table on DB2 v11, and I need to query a subset of it as efficiently as possible. All I need is the total count of the set (not known in advance, it's based on criteria, lets say 1 day) and the ID of the first record, and the ID of the last record.
The old code was fetching the entire table, then just using the 1st record ID, and the last record ID, and size, and not making use of the rest. Now this code is timing out. It's a complex query of several joins.
IS there a way to just fetch the size of the set, 1st record, last record all in one select query ?
I've read that reordering the list in order to fetch the 1st record(so fetch with Desc, then change to Asc) is not efficient.
sample table 1 TRANSACTION_RECORDS:
tdID TIMESTAMP name
-------------------------------
123 2020-03-31 john
234 2020-03-31 dan
456 2020-03-01 Eve
675 2020-04-01 joy
sample table 2 TRANSACTION_TYPE:
invoiceId tdID account
------------------------------
897 123 abc
898 123 def
877 234 mnc
899 456 opp
Sample query
select Min(tr.transaction_id), Max(tr.transaction_id)
from TRANSACTION_RECORDS TR
join TRANSACTION_TYPE TT
on TR.tdID=tt.tdID
WHERE Date(TR.TIMESTAMP) = '2020-03-31'
group by tr.tdID
order by TR.tdID ASC
This results in multiple columns, (but it requires the group by)
123,123
234,234
456,456
What I want is:
123,456
As I mentioned in the comments, for this query you don't need Group BY and neither Order by, just do:
select Min(tr.transaction_id), Max(tr.transaction_id)
from TRANSACTION_RECORDS TR
join TRANSACTION_TYPE TT
on TR.tdID=tt.tdID
WHERE Date(TR.TIMESTAMP) = '2020-03-31'
It should work as expected

Create column based on grouping other values

I have difficulties formulating my issue.
I have a view which brings these results. There's a need to add a column to the view, which will pair up round-trip flights with identical number.
Flt_No From_Airport To_Airport Dep_Date RequiredResult
124 |LCA |CDG |10/19/14 5:00 1
125 |CDG |LCA |10/19/14 10:00 1
197 |LCA |BCN |10/4/12 5:00 2
198 |BCN |LCA |10/4/12 11:00 2
501 |LCA |HER |15/8/12 12:05 3
502 |HER |LCA |15/8/12 15:15 3
I.e. flight 124 is going from Larnaca to CDG, and flight 125 is going back from CDG to Larnaca - they both have to have the same identifier.
Round-trip flights will always have following flight numbers.
I have a bunch of conditions which I won't write now.
Omitting hours is not an option, they're important.
I was thinking dense_rank() but I don't know how to create one identifier for 2 flights with different numbers, please help.
If your data is similar to the sample data posted, then the following query should give the required result:
SELECT *,
DENSE_RANK() OVER (ORDER BY CASE
WHEN From_Airport < To_Airport THEN From_Airport
ELSE To_Airport
END)
FROM mytable
Join conditions are not limited to simple equality. Assuming {Flight No, Departure, Destination} is unique on any one day, then a self join should do it:
select whatever
from flights outbound
inner join flights inbound on outbound.flt_no+1 = inbound.flt_no
and cast(outbound.dep_date, date)
= cast(inbound.dep_date, date)
and outbound.From_Airport = inbound.To_Airport
and outbound.To_Airpott = inbound.From_Ariport