SQL query - select row basing on the joined table's criteria - sql

I'm stuck within this simple scenario:
tableA
| ID | TableB_ID | Name |
tableA 1 ---> * tableB
tableB
| ID | Status_ID |
and I need to retrieve the Name column values from the tableA, whose contains rows in the tableB with Status_ID = 1 and Status_ID = 2 (two separate rows, it can be more with other values but it doesn't matter here)

Try this:
SELECT A.NAME
FROM TABLE_A AS A INNER JOIN TABLE_B AS B ON A.TABLEB_ID = B.ID
WHERE B.STATUS_ID IN (1, 2) -- OR OTHER VALUES

Related

Update select using the max of one column Postgresql

So I'm changing a db structure. I'm moving a column, 'size', from table_B to table_A.
Table_B can have multiple entries referencing table_A.a_id
I want to update the new 'size' column in table_A from table_B with the row with the highest b_id.
So I can use Max() and group by to select just the highest b_ids for each a_id.
SELECT max(b_id)
FROM table_B
GROUP BY a_id;
But I'm not sure how to fit that in with the update select
UPDATE table_A
SET table_A.size = table_B.size
FROM table_A, table_B
WHERE table_A.a_id = table_B.a_id
AND table_B.b_id =
(
max...
);
edit:
I realise now this actually isn't an update select, my first attempt was
How table_B looks and the expected result in table_A
table_A
a_id | size
-------------------------
1 | 5678
2 | 456
table_B
b_id | a_id | size
--------------------------------------
1 | 1 | 1234
2 | 1 | 5678
3 | 2 | 456
First, write a select to get the size you want:
select distinct on (b.a_id) b.a_id, b.size
from tableb b
order by b.a_id, b.b_id desc;
Next, incorporate this into the update:
update tablea a
set size = b.size
from (select distinct on (b.a_id) b.*
from tableb b
order by b.a_id, b.b_id desc
) b
where a.a_id = b.a_id;
you can try the following query
UPDATE table_A
SET table_A.size =
( SELECT table_B.size
FROM table_B B1
WHERE table_A.a_id = B1.a_id AND
B1.b_id = (SELECT max(b_id) FROM table_B B2 WHERE table_A.a_id=B2.a_id))

Stop returning multiple similar rows on joins

I have the following scenario in SQLite.
TableA
ID
-----
1 |
2 |
3 |
Table B
ID | AID |Tag
----------------
1 | 1 | Hide
2 | 1 | Show
3 | 2 | Null
4 | 3 | Show
Table B has column AID which is the IDs of table A.
In the example above
Table A ID: '1' has
-> Table B ID of '1' and '2' and Tags 'Hide' and 'Show' attached to it.
I am looking for an SQL that will only return, in the example above, Table A IDs: '2' and '3'.
Basically, as TableA ID: '1' has a 'Hide' tag attached to it, don't return it (even though it also has a show tag attached to it)
The SQL I am using is (excuses the names, this is just a quick example)
select
a.ID as a_ID,
b.ID as b_ID,
b.Tag as Tag
from
Table A as a
left join Table B on a.id = b.aID
and b.tag != 'hide'
The problem with this SQL it's still returning
a_ID | b_ID | Tag
-------------------------------
1 | 2 | Show
I'm a tad stuck and any help would be really appreciated. I'm not 100% sure how I would work this on for a google search.
The closest I got was this question How to return only 1 row if multiple duplicate rows and still return rows that are not duplicates?
but I couldn't work out how the GROUP BY would help here.
You're looking for an id where no row exists with a 'hide' tag. This is a direct translation into SQL:
select *
from TableA as a
where not exists
(
select *
from TableB as B
where a.id = b.aID
and b.tag = 'hide'
)
Or, if you want the data from TableB:
select *
from TableB as t1
where not exists
(
select *
from TableB as t2
where t1.aID = t2.aID
and t2.tag = 'hide'
)
You could use an extra condition with the exists operator:
SELECT a.ID AS a_ID, b.ID AS b_ID, b.Tag AS Tag
FROM table_a a
LEFT JOIN table_b b ON a.id = b.aID
WHERE NOT EXISTS (SELECT *
FROM table_b bin
WHERE bin.aID = a.ID AND bin.Tag = 'hide')

TSQL - retrieve results from table A that contains exact data contained in table B

I have TableA (id bigint, name varchar) and TableB (name varchar) that contains the following data:
Table A: Table B: Results:
------------- --------- ---------------
| 1 | "A" | | "A" | | 1 | "A" |
| 1 | "B" | | "B" | | 1 | "B" |
| 2 | "A" | --------- | 4 | "A" |
| 3 | "B" | | 4 | "B" |
| 4 | "A" | ---------------
| 4 | "B" |
-------------
I want to return results from TableA that contains an EXACT match of what's in table B.
Using the 'IN' clause only retrieves back an occurrence.
Also, another example, if TableB has only "A", I want it to return back: 2-"A"
I understand your question but it is a tricky one as not exactly in line with the relational logic. You are looking for id's for which SELECT name FROM TableA WHERE id IN ... ORDER BY name; is identical to SELECT name FROM B order by name;.
Can you assume that A(id,name) is unique and B(name) is unique? Better said, are there constraints like that or can you set them up?
If yes, here is a solution:
1. Get rid of ids in A with rows not matching the rows in B
SELECT id, A.name FROM A WHERE id NOT IN
(SELECT id FROM A LEFT JOIN B ON A.name = B.name WHERE B.name IS NULL);
2. Count rows per each id (this is why the unique constraints are necessary)
SELECT id, COUNT(*) FROM
(
SELECT id, A.name FROM A WHERE id NOT IN
(SELECT id FROM A LEFT JOIN B ON A.name = B.name WHERE B.name IS NULL)
) t
GROUP BY id;
3. Only retain those that match the number of rows of B.
SELECT id, COUNT(*) FROM
(
SELECT id, A.name FROM A WHERE id NOT IN
(SELECT id FROM A LEFT JOIN B ON A.name = B.name WHERE B.name IS NULL)
) t
GROUP BY id
HAVING COUNT(*) = SELECT COUNT(*) FROM B;
This works in SQL Server
select * from TableA a
where
(select count(*) from TableB) = (select count(*) from TableA where id = a.id) and
(select count(*) from TableB) =
(
select count(*) from
(
select name from TableA where id = a.id
intersect
select name from TableB
) as b
)

Postgresql tables intersect

I have a two tables in my postgresql database.
Both tables have same columns.
How can i prefer values from tableA which are not null?
TableA
id | name
1 | val_a_1
2 | val_a_2
3 | (null)
TableB
id | name
1 | (null)
2 | val_b_2
3 | val_b_3
Result which i want to get:
id | name
1 | val_a_1
2 | val_a_2
3 | val_b_3
For now I've got it like this, but its more complicated, because there are lots of columns.
SELECT *
CASE
WHEN TableA.name is NULL or TableA.name = ''
THEN (SELECT TableB.name FROM TableB where TableB.id = 1)
ELSE TableA.name
END
AS name,
CASE
.
. another columns
.
END
Thanks
why not use COALESCE? Assuming all recordID in tableA is present on Table2
SELECT a.ID,
COALESCE(a.name, b.name) AS "Name"
FROM TableA a
INNER JOIN TableB b
ON a.ID = b.ID
SQLFIddle Demo
Conditional Expressions
The COALESCE function returns the first of its arguments (there can be more arguments) that is not null.
It's all about the COALESCE, not the join itself.
you can use a full outer join for the values which exist in tableA but not in tableB and vice versa:
select coalesce(tableA.ID, tableB.ID) as ID,
coalesce(tableA.Name, tableB.Name) as Name
from tableA full outer join tableB on tableA.ID = tableB.ID

How to find row where one table has NULL values and other has values

I am trying to write a script which will give me distinct rows from table which has NULL value in Table A but for same columns Table B has values.
Scenario: I have 2 Tables:
Table A and Table B have the same columns
The values in Table A are
| ID | Name | LicenseNo | NationalLicenseNumber |
| 1 | 'ABC,XYZ' | NULL | NULL |
| 1 | 'CDS,ABD' | NULL | NULL |
Table B has values like :
| 1 | 'XYZ ABC' | 1234567 | 976633 |
| 1 | 'ABD CDS' | 4324223 | 304242 |
and so on... I want to display the result which shows me value in all columns from both tables.
Any help would be appreciated
Thanks
Try this select:
select a.ID,a.Name,a.LicenseNo,a.NationalLicenseNumber,
b.ID,b.Name,b.LicenseNo,b.NationalLicenseNumber
from TableA a
left outer join TableB b on a.ID=b.ID
where
((a.Name is null) and (b.Name is not null))
or ((a.Name is not null) and (b.Name is null))
((a.LicenseNo is null) and (b.LicenseNo is not null))
or ((a.LicenseNo is not null) and (b.LicenseNo is null))
((a.NationalLicenseNumber is null) and (b.NationalLicenseNumber is not null))
or ((a.NationalLicenseNumber is not null) and (b.NationalLicenseNumber is null))
It joins both tables on ID, and keeps only the rows where null-ness of the corresponding columns is different.
EDIT Replaced (a.Name is null) <> (b.Name is null) that causes syntax errors with a longer expression that does not compare booleans.
This will work. Also, it addresses the issue of the second set of columns with identical nam es returning simply as "Expr_1", "Expr_2", etc by aliasing the columnNames of TableB.
This returns all the rows in TableB (Which, according to your posting, conotain all the proper values) and joins them on the ID field to rows in TableA (Which you say may have rows with NULL values in any of the other fields). This will return records for both tables where the ID's match, and where any one or more of the associated fields in TableA are null.
SELECT
a.ID,
a.Name,
a.LicenseNo,
a.NationalLicenseNo,
b.ID AS b_ID,
b.Name AS b_Name,
b.LicenseNo AS b_LicenseNo,
b.NationalLicenseNo AS b_NationalLicenseNo
FROM
TableA AS a RIGHT OUTER JOIN
TableB AS b ON a.A = b.A
WHERE
(a.Name IS NULL) OR
(a.LicenseNo IS NULL) OR
(a.NationalLicenseNo IS NULL)
Try simply check if is not null:
SELECT *
FROM TABLE_A
WHERE Name IS NOT NULL AND LicenseNo IS NOT NULL AND NationalLicenseNumber IS NOT NULL
UNION
SELECT *
FROM TABLE_B
WHERE Name IS NOT NULL AND LicenseNo IS NOT NULL AND NationalLicenseNumber IS NOT NULL