T-SQL Select all from TableA and condition on TableB - sql

TableA Columns: A_ID, NAME, SOURCE, TITLE, EVENTID
TableB Columns: B_ID, EVENTID, CODE, FIELD
How do I extract NAME, SOURCE, TITLE and FIELD or null (if there is CODE=x) ? Example should show it better. It's T-SQL on SQL Server Express.
Example:
TableA | TableB
-----------------------------------------------------------------------
A_ID, NAME, SOURCE, TITLE, EVENTID | B_ID, EVENTID, CODE, FIELD
-----------------------------------------------------------------------
1 john s1 x 100 | 1 100 5 textA
2 bruce s2 y 105 | 2 100 10 textB
3 bob s3 z 110 | 3 105 5 textC
| 4 110 5 textD
| 5 110 10 textE
There is no code 10 for EventId 105 so the result should be null. How do write a SELECT quesry that would give me such result:
[ john | s1 | x | textB ]
[ bruce | s2 | y | ]
[ bob | s3 | z | textE ]
It might be really easy but I can't figure it out.. Thanks in advance.

You need an OUTER JOIN between the tables
SELECT A.NAME,
A.SOURCE,
A.TITLE,
B.FIELD
FROM TableA A
LEFT JOIN TableB B
ON A.EVENTID = B.EVENTID
AND B.CODE = 10
The B.CODE = 10 condition needs to go in the JOIN not a WHERE clause to avoid effectively turning the query back into an INNER JOIN.
This can return multiple rows for a particular A value if there is more than one joining record but it is not clear from your question if this is possible in your data anyway (and if so which B.Field value should be used) and this may well be your desired behaviour.

This should do it
SELECT a.NAME, a.SOURCE, a.TITLE, b.FIELD
FROM TableA a
LEFT JOIN TableB b ON b.EventId = a.EventId
AND b.Code = 10

Related

Joing on SQL table with arrays

I have two SQL tables
TABLE A
id | user | embedding
-----------------------
1 Ram [.12,.56]
2 Shyam [.23,.24]
3 Ghanshyam [.23,.39]
4 Balram [.34,.39]
TABLE B
--------------------
id | users
--------------------
1 [Ram,Shyam]
2 [Ram,Ghanshyam]
3 [Ram, Balram]
And I want to have a query that will return essentially table B but with the users replaced by their embeddings.
Desired output
-----------------------------
id | users
-----------------------------
1 [[.12,.56],[.23.,.24]]
2 [[.12,.56],[.23,.39]]
3 [[.12,.56], [.34,.39]]
How can I do this?
how about using unnest and array_agg:
select b.id , array_agg(embedding)
from TableB b
cross join unnest(b.users) c(user)
join TableA a
on c.users = a.user
group by b.Id

Using multiple joins (e.g left join)

I would like to know what's the logic for multiple joins (for example below)
SELECT * FROM B returns 100 rows
SELECT B.* FROM B LEFT JOIN C ON B.ID = C.ID returns 120 rows
As I know using left join will returns any matching data from the left table which is B if data are found for both table. But how come when using left join, it returns more data than table B itself?
What am I do wrong or misunderstood here? Any guidance are very appreciated. Thanks in advance.
Let be table B:
id
----
1
2
3
Let be table C
id name
------------
1 John
2 Mary
2 Anne
3 Stef
Any id from b is matched with ids from c, then id=2 will be matched twice. So a left join on id will return 4 rows even if base table B has 3 rows.
Now look at a more evil example:
Table B
id
----
1
2
2
3
4
table C
id name
------------
1 John
2 Mary
2 Anne
3 Stef
Every id from b is matched with ids from c, then first id=2 will be matched twice and second id=2 will be matched twice so the result of
select b.id, c.name
from b left join c on (b.id = c.id)
will be
id name
------------
1 John
2 Mary
2 Mary
2 Anne
2 Anne
3 Stef
4 (null)
The id=4 is not matched but appears in the result because is a left join.
Look at the following example :
B = {1,2}
C = {(1,a),(1,b),(1,c),(1,d),(1,e)}
The result of B left join C will be :
1 | a
1 | b
1 | c
1 | d
1 | e
2 | null
The number of rows in the result is definitely larger than rows in B (2).
In general the number of rows in result of B left join C is bounded by B.size + C.size and not only by B.size as you think...
As per your query it do the join to B Table with C and B table is Left Table so it will display all the records of Left table in our case it is B and related from other Table in our Case it is C.

comparing rows in sql on two different columns

id address retailer
1 A 11
2 A 11
3 A 11
4 A 12
5 A 13
6 B 12
7 B 12
8 B 13
My output should be
id address retailer
1 A 11
4 A 12
5 A 13
6 B 12
8 B 13
i.e my query should return id's which have same address but not same retailer.
How toget this?
Try to use group by clause as below:
select min(id), address, retailer
from tab
group by address, retailer
Assuming you're joining on columns with no duplicates, which is by far the most common case:
An inner join of A and B gives the result of A intersect B, i.e. the inner part of a venn diagram intersection.
An outer join of A and B gives the results of A union B, i.e. the outer parts of a venn diagram union.
Examples:
Suppose you have two Tables, with a single column each, and data as follows:
A B
- -
1 3
2 4
3 5
4 6
Note that (1,2) are unique to A, (3,4) are common, and (5,6) are unique to B.
Inner join:
An inner join using either of the equivalent queries gives the intersection of the two tables, i.e. the two rows they have in common.
select *
from a
INNER JOIN b on a.a = b.b;
select a.*,b.*
from a,b
where a.a = b.b;
a | b
--+--
3 | 3
4 | 4
Left outer join:
A left outer join will give all rows in A, plus any common rows in B.
select *
from a
LEFT OUTER JOIN b on a.a = b.b;
select a.*,b.*
from a,b
where a.a = b.b(+);
a | b
--+-----
1 | null
2 | null
3 | 3
4 | 4
Full outer join:
A full outer join will give you the union of A and B, i.e. All the rows in A and all the rows in B. If something in A doesn't have a corresponding datum in B, then the B portion is null, and vice versa.
select *
from a
FULL OUTER JOIN b on a.a = b.b;
a | b
-----+-----
1 | null
2 | null
3 | 3
4 | 4
null | 6
null | 5
select min(id) as id,address, retailer
from table1
group by address, retailer
order by id
The query you need is:
SELECT min(id), address, retailer
FROM table1 AS t1
group by address, retailer
order by address
Here's the source
Use This: It's working:
SELECT * FROM `sampletable` GROUP BY address, retailer

Get the max value of a column from set of rows

I have a table like this
Table A:
Id Count
1 4
1 16
1 8
2 10
2 15
3 18
etc
Table B:
1 sample1.file
2 sample2.file
3 sample3.file
TABLE C:
Count fileNumber
16 1234
4 2345
15 3456
18 4567
and so on...
What I want is this
1 sample1.file 1234
2 sample2.file 3456
3 sample3.file 4567
To get the max value from table A I used
Select MAX (Count) from A where Id='1'
This works well but my problem is when combining data with another table.
When I join Table B and Table A, I need to get the MAX for all Ids and in my query I dont know what Id is.
This is my query
SELECT B.*,C.*
JOIN A on A.Id = B.ID
JOIN C on A.id = B.ID
WHERE (SELECT MAX(COUNT)
FROM A
WHERE Id = <what goes here????>)
To summarise, what I want is Values from Table B, FileNumber from Table c (where the count is Max for ID from table A).
UPDATE: COrrecting table C above. Looks like I need Table A.
I think this is the query you're looking for:
select b.*, c.filenumber from b
join (
select id, max(count) as count from a
group by id
) as NewA on b.id = NewA.id
join c on NewA.count = c.count
However, you should take into account that I don't get why for id=1 in tableA you choose the 16 to match against table C (which is the max) and for id=2 in tableA you choose the 10 to match against table C (which is the min). I assumed you meant the max in both cases.
Edit:
I see you've updated tableA data. The query results in this, given the previous data:
+----+---------------+------------+
| ID | FILENAME | FILENUMBER |
+----+---------------+------------+
| 1 | sample1.file | 1234 |
| 2 | sample2.file | 3456 |
| 3 | sample3.file | 4567 |
+----+---------------+------------+
Here is a working example
Using Mosty’s working example (renaming the keyword count to cnt for a column name), this is another approach:
with abc as (
select
a.id,
a.cnt,
rank() over (
partition by a.id
order by cnt desc
) as rk,
b.filename
from a join b on a.id = b.id
)
select
abc.id, abc.filename, c.filenumber
from abc join c
on c.cnt = abc.cnt
where rk = 1;
select
PreMax.ID,
B.FileName,
C2.FileNumber
from
( select C.id, max( C.count ) maxPerID
from TableC C
group by C.ID
order by C.ID ) PreMax
JOIN TableC C2
on PreMax.ID = C2.ID
AND PreMax.maxPerID = C2.Count
JOIN TableB B
on PreMax.ID = B.ID

SQL Select Statement issue - returning rows conditionally on a 2nd table

I could really use some help with the following SQL Select statement scenario:
I need to select all rows from a table conditionally depending on whether a userID has already entered data into a second table with the same ID.
Example:
Select all rows from TABLE A for idNumber where idNumber not in
TABLE B
but for each idNumber that IS in TABLE B, still return row unless a
specific userID is in that row in TABLE B.
TABLE A
========
idNumber|type|Date
1 A 01/01/01
2 A 01/01/01
3 B 01/01/01
4 B 01/01/01
5 B 01/01/01
TABLE B
========
idNumber|type|userID
1 A 0000
3 B 0000
4 B 1111
userID to exclude records for = 1111
SQL Query should return:
idNumber|type|Date
1 A 01/01/01
2 A 01/01/01
3 B 01/01/01
5 B 01/01/01
Apologies for the long winded post but i hope it makes sense.
Many thanks in advance,
ukjezza.!!
Select idNumber, type, Date
From TableA
Where Not Exists (
Select 1
From TableB
Where TableB.idNumber = TableA.idNumber
And TableB.userID = 1111
)
Another choice:
Select TableA.idNumber, TableA.type, TableA.Date
From TableA
Left Join TableB
On TableB.idNumber = TableA.idNumber
And TableB.userId = 1111
Where TableB.idNumber Is Null
Looks like a LEFT JOIN and COALESCE could take care of it:
SELECT a.*
FROM TableA as a
LEFT JOIN TableB as b
ON a.idNumber = b.idNumber
WHERE COALESCE(b.userID, -1) != 1111
select A.*
from TableA as A
left outer join TableB as B
on A.idNumber = B.idNumber
where B.idNumber is null or
B.userID <> '1111'