Postgres - Cannot Join Json Array Values on UUID - arrays

So I have one table Profession:
UUID UUID,
Name TEXT
Where UUID is uuid1, uuid2, uuid3, etc.
Then another table Degrees:
DegreeName TEXT,
Record JSON
Where the Record->'Professions' json record may contain a list of Profession.uuid, such as {"Professions":"[uuid1,uuid2]"}, though the field could be NULL such as {"Professions":"[]"}.
Here is how I am trying to join the two tables:
SELECT prof.uuid, prof.Name, d.DegreeName
FROM Profession prof
LEFT JOIN (
SELECT DegreeName, json_array_elements(Record->'Professions') prof_uuid
FROM Degrees
) d
ON d.prof_uuid::TEXT=prof.uuid::TEXT
When I do this, I only get Nulls. Note that I cast to TEXT because I cannot cast the Professions array to a UUID because of blanks.
I have tried manually searching for the Profession table using a value from the Professions list and it works:
SELECT *
FROM Profession
WHERE uuid = 'someprofuuid'
Is there some cast I missing?

I figured it out. The problem was I was using json_array_elements instead of json_array_elements_text. When I switched that, the join worked:
SELECT prof.uuid, prof.Name, d.DegreeName
FROM Profession prof
LEFT JOIN (
SELECT DegreeName, json_array_elements_text(Record->'Professions') prof_uuid
FROM Degrees
) d
ON d.prof_uuid::TEXT=prof.uuid::TEXT

Related

How to save a value from a column after searching for a particular record in SQL

I want to search for a record using values in two columns of a table, but then save a value from another column of this same record as a variable. For example:
SELECT * FROM Courses WHERE CourseName = 'Psych101' AND FY = '2020'
There is another column called "CourseID", so what I need to do is find the course using the simple query above, then capture the value in the CourseID column and save it as a variable to call later on in a script.
Since it looks like you are looking for one specific record, you can DECLARE a variable in sql-server.
A quick example to declare a variable and store a value
DECLARE #PyschCourseID (REPLACE WITH TYPE OF COURSEID)
SELECT #PyschCourseID = CourseID
FROM Courses
WHERE CourseName = 'Psych101' AND FY = '2020'
However, if you are only using this value once, I would recommend a JOIN on the [Courses] table if some foreign key relationship exists. For example:
UPDATE TableB
SET Col = #newValue
FROM TableB B
JOIN Courses c ON c.CourseID = B.CourseID
WHERE c.CourseName = 'Psych101' AND c.FY = '2020'

How to perform join between on float type id column and one string having multiple ids seperated by comma

I have to join id of two sets where in on set has multiple ids and another table has only one id. My query is:
Select * from(Select('1301,1303,1305,1307,1309,1311,1313,1315') IDs from market group by market.Segment)P join DST d on p.IDs = d.ID
One thing to note is '1301,1303,1305,1307,1309,1311,1313,1315' is value coming from dynamic query so I can not manipulate this value (to 1301,1303,1305,1307,1309,1311,1313,1315).
In this query,d.ID is float type. This query does not work.
My aim is to find any record from DST table that has at least on id among ids 1301,1303,1305,1307,1309,1311,1313,1315.
How can I do this?
You can use IN clause :
select m.*
from market m
where m.id in (1301,1303,1305,1307,1309,1311,1313,1315);
If ids are in string format then you can do :
select m.*
from market m cross apply
dbo.string_split('1301,1303,1305,1307,1309,1311,1313,1315', ',') mm
where mm.value = m.id;

Full Outer Join Mismatching

new to this type of request in Microsoft SQL Server. I'm using a full outer join on two tables looking for records that are not matching in the right table (New) vs left table (Old). I'm trying to find the new scores from the new table so I can update a production table with the most recent scores, while still holding onto old scores that have not been updated yet. This is my set up
Select
a.customer
,a.date
,a.Cat score
,a.Dog score
,a.Mouse score
,b.customer
,b.date
,b.Cat score
,b.Dog score
,b.Mouse score
From Old Table a
Full Outer Join New Table b
ON a.customer = b.customer
AND a.date = b.date
AND a.Cat score = Cast(b.Cat score as Varchar)
AND a.Dog score = Cast(b.Dog score as Varchar)
AND a.Mouse score = Cast(b.Mouse score as Varchar)
Note--- Have to cast the scores as Varchar or else I could not get the join to work. "Conversion failed when converting the varchar value '9.0000' to data type int."
Results:
Both lists are 100% different without any matches
This can't be true because I can search the records in both tables manually and find the exact same result in both tables. Maybe there is a better way to do this type of update?
Your problem is the strings 9 and 9.0000 are not equal. They do not join. These table variables will be used to demo this:
DECLARE #TableA TABLE
(
CatScore Int
)
;
DECLARE #TableB TABLE
(
CatScore VARCHAR(10)
)
;
INSERT INTO #TableA (CatScore) VALUES (9);
INSERT INTO #TableB (CatScore) VALUES ('9.0000');
The first example highlights the mismatch.
Mismatching Join Example
SELECT
*
FROM
#TableA AS a
FULL OUTER JOIN #TableB AS b ON b.CatScore = CAST(a.CatScore AS VARCHAR(50))
Returned Value
CatScore CatScore
9 NULL
NULL 9.0000
What you need to do is match the data types and then the values. This example assumes:
Table A stores cat score as a integer.
Table B stores the same as a varchar.
Table B always includes 4 zeros after a full stop.
Matching Example
SELECT
*
FROM
#TableA AS a
FULL OUTER JOIN #TableB AS b ON b.CatScore = CAST(a.CatScore AS VARCHAR(50)) + '.0000'
Returns
CatScore CatScore
9 9.0000
Here the integer 9 has been cast into a varchar. The full stop and trailing zeros have then been added. It's not a decimal place, as these aren't really numbers.
The lesson to takeaway from this exercise is; always use the correct data type. Storing numbers in strings will cause problems further down the line.
UPDATE
It would make more sense to CAST both fields into a DECIMAL. Both integers and varchars, containing numeric like data, can be converted into decimals. When casting fields for matching you want to find the smallest data type that will hold all input from both source fields.

How to get corresponding names for each element of an Postgresql array

I have two tables tablea and tableb. Their sturcture is:
tablea
id serial
name varchar
alg integer[]
tableb
id serial
description varchar
in tablea.alg field I have multiple numbers of substances like {1,17,55,97} and in the query I want to get names instead of numbers like:
name | substances
organism1 | substance 1, substance 17, substance 55, substance 97
Can any1 suggest the right query?
Answer to simmilar question is on StackOwerflow question, but how to use tables instead of fixed array values?
Thank you...
Use unnest() to get algs in separate rows,
join tableb on the values and aggregate description with string_agg():
select name, string_agg(description, ', ') substances
from (
select name, unnest(alg) alg
from tablea
) a
join tableb on alg = id
group by name;

How to extract json array elements in postgresql

What I want to do is sum 29.0 and 34.65 and group by P_id
Table: transaction_items
Column name: Debits, P_id
Column data type: text, text
Data:
Debits
[{"amount":29.0,"description":"Fee_Type_1"}
[{"amount":"34.65","description":"Fee_Type_1"}
P_id
16
16
I tried using the solution mentioned here [https://stackoverflow.com/questions/27834482/how-to-get-elements-from-json-array-in-postgresql][1]
select     transaction_line_items.P_id,
           each_attribute ->> 'amount' Rev
from       transaction_line_items
cross join json_array_elements(to_json(Debits)) each_section
cross join json_array_elements(each_section -> 'attributes') each_attribute
where      (each_attribute -> 'amount') is not null;
However, I got an error saying "cannot deconstruct a scalar".
Can someone please let me know how to parse the values I am looking for?
Thank you.
It seems that your data is broken. The values of Debits column are not valid json due to the lack of right square brackets. Assuming that your data should look like this:
[{"amount":29.0,"description":"Fee_Type_1"}]
[{"amount":"34.65","description":"Fee_Type_1"}]
the following query does what you want:
select p_id, sum(amount)
from (
select p_id, (elements->>'amount')::numeric amount
from transaction_items
cross join json_array_elements(debits::json) elements
) sub
group by p_id;

Resources