LEFT JOIN for current row in primary table - sql

This is the question about JDBC. I have next task. I'm iterating through rows from table A and for some current row I want to execute some query against table B in context of current row from A. For example, if I have some query like
SELECT B.description FROM A LEFT JOIN B ON A.ID = B.refId
then I want to get all results where B.refId="current row from A".ID. Please, note that I cannot modify query for selecting results from B.
For example, let's table A like this:
ID name
1 nameA
2 nameB
and table B:
ID description refID
1 desc1 1
2 desc2 1
3 decs3 2
4 desc4 2
So if I for example on row from table A with ID 2 and perform my query then I want to get "desc3" and "desc4" only.
I suggest that this task can be solved with cursors but I'm familiar with it. Can anyone give me a hint?

Based on the question
SELECT B.description FROM
A
INNER JOIN
B ON A.ID = B.refId
WHERE
A.ID = 2
SELECT B.description FROM
B
WHERE
B.refid = 2
Otherwise, I don't think we understand the question...

What is your question? The query you gave means "all results where B.refId=current row from A.ID".

Can you just make your description.
A.*
Not sure if I understand the question though.

Related

SQL 'belong to' logic

So, I have been trying to write a query in SQL but facing an issue. I am trying to write a 'belongs to' kind of condition. What I want to do is if the values being fetched belongs to a column in another table then populate one thing otherwise populate null.
for ex.
NAME table
ID NAMES
1 A
2 B
3 C
4 D
5 E
XYZ table
ID
2
4
5
I wrote the query something like this
(CASE WHEN NAME.ID IN (SELECT ID FROM XYZ) THEN NAME.NAMES ELSE NULL END ) AS 'ABC'
This query does run but it has been running for 14 hours (OBVIOUSLY FOR A VERY HUGE AMOUNT OF DATA) and still there is no result. Is there some flaw in this logic or is there some better way it could be done?
I expect a result like this:
ABC
NULL
B
NULL
D
E
You just need a plain left join here:
SELECT
CASE WHEN t2.ID IS NOT NULL THEN t1.NAMES END AS ABC
FROM NAME t1
LEFT JOIN XYZ t2
ON t1.ID = t2.ID;
Demo
Note that a CASE expressions else condition, if not explicitly specified, defaults to NULL. This behavior works here because you want to render NULL if a given record in the NAME table does not match to any record in the XYZ table.
The problem isn't your logic. It is simply how the code is optimized. The subquery is probably being run for each row in the outer query.
I would recommend switching to exists:
(case when exists (select 1 from xyz where xyz.id = name.id) then name.names
end) as abc
This maintains the semantics of your original query. In particular, there is no danger that duplicates in xyz would return multiple rows (as would happen with a left join).
For performance for this -- or for the left join -- you want an index on xyz(id).

how to update a column in a table by joining another table with only certain rows getting updated

I have two tables, A and B
Table A
ID | value
------ | ------
1 | 20
2 | 21
3 | 25
Table B
ID | value
------ | ------
1 | 15
2 | 10
And I need to update the value column of table A, with the corresponding values of table B. The issue is Table A gets updated every day and, when ever it gets updated- it updates with the same old values, so I need to create a query so that it can be used as a package for scheduling it to run everyday with the correct values.
Also, some of the IDs and its corresponding values which are not present in Table B, should not be altered. Can someone help me with this.
I am using sql server 2014
This is the Query that I am using.
SELECT A.[SUBSTAT_NAME]
,A.[FDR_NUM]
,A.[XFMR_ID]
,A.[XFMR_SIZE]
,B.DRG_size
,A.[PAD_R]
,A.[CONDUCT_ID]
,A.[PHASE]
,A.[SRV_LOC_NUM]
,A.[BUS]
,A.DATE_TIME
FROM [SERV_LOC_XFMR_GIS_PROD] A left join
[XFMR_LESS_THAN_10] B
on A.XFMR_ID = B.XFMR_ID
So I need the DRG_SIZE value to be replaced with XFMR_SIZE, when the XFMR_ID match. But the rest of the IDs in Table A should not be altered and should be displayed in the results
You will need to use the following general syntax:
update a
set a.c1 = b.c1
from tableA as a
inner join tableB as b on b.c2 = a.c2
First test that with
select a.c1, a.c2, b.c1, b.c2
from tableA as a
inner join tableB as b on b.c2 = a.c2
and see if your join produces the correct results. Then write an update statement.
Try this, but make sure to save a backup first:
UPDATE A
SET A.value = B.value
FROM A, B
WHERE A.id = B.id

SQL: Sort a table by the first relation to a second table

I have a Many-to-Many relationship between two tables. I'd like to sort the first table by the first relationship with the second table and only return a single result from that table. This is on SQL Server. I'd like something like this:
SELECT a.retrieve_me
FROM table_A AS a
JOIN table_B AS b ON a.foo = b.foo
JOIN table_C AS c ON b.bar = c.bar
ORDER BY c.sort_me
Unfortunately it returns MN(k) results, where M is the count of "table_A" and N(k) is the number of relations of a single row k with "table_C." To have it return just the results I wanted without post filtering I tried using DISTINCT on the SELECT clause and using TOP(SELECT COUNT(*) FROM table_A) but neither are valid syntax.
Any ideas? Hoping I can make this as performant as possible.
EDIT:
For clarity
table A
------------
"joe" 1
"betty" 2
"george" 3
table B
------------
1 2
1 3
2 3
2 4
3 1
table C
------------
1 "ashton"
2 "harding"
3 "spring"
4 "merry lane"
I'd like the results returned in the order of "george", "joe", and "betty" which is in the order (george -> ashton, joe -> harding, betty -> merry lane.)
If I understood correctly what you need, cause I think is very hard to follow you .. this should do it:
SELECT a.nm
FROM tablea a
cross apply (select top 1 *
from tableb b
join tablec c on b.id2 = c.id
where a.id = b.id1
order by c.nm) bc
order by bc.nm
http://sqlfiddle.com/#!3/661c0/5/0

Select from one table matching criteria in another?

I'd really appreciate some help with an SQL query across tables. I realise this sort of thing is asked constantly, but I can't find a similar enough question to make sense of the answers.
I want to select rows from table_A that have a corresponding tag in table_B.
So, for example, " select rows from table_a which are tagged 'chair' " would return table_C.
Also, id is a unique in table_a, and not in table_b.
table_A: table_B: table_C:
id object id tag id object
1 lamp 1 furniture 3 stool
2 table 2 furniture 4 bench
3 stool 3 furniture
4 bench 4 furniture
4 chair
3 chair
Alternatively, is there a better way to organise the data?
The simplest solution would be a correlated sub select:
select
A.*
from
table_A A
where
A.id in (
select B.id from table_B B where B.tag = 'chair'
)
Alternatively you could join the tables and filter the rows you want:
select
A.*
from
table_A A
inner join table_B B
on A.id = B.id
where
B.tag = 'chair'
You should profile both and see which is faster on your dataset.
You should make tags their own table with a linking table.
items:
id object
1 lamp
2 table
3 stool
4 bench
tags:
id tag
1 furniture
2 chair
items_tags:
item_id tag_id
1 1
2 1
3 1
4 1
3 2
4 2
select a.id, a.object
from table_A a
inner join table_B b on a.id=b.id
where b.tag = 'chair';
I have a similar problem (at least I think it is similar). In one of the replies here the solution is as follows:
select
A.*
from
table_A A
inner join table_B B
on A.id = B.id
where
B.tag = 'chair'
That WHERE clause I would like to be:
WHERE B.tag = A.<col_name>
or, in my specific case:
WHERE B.val BETWEEN A.val1 AND A.val2
More detailed:
Table A carries status information of a fleet of equipment. Each status record carries with it a start and stop time of that status. Table B carries regularly recorded, timestamped data about the equipment, which I want to extract for the duration of the period indicated in table A.

sql left join and duplicates in result

Say I have 2 tables, A and B, each A entity can possibly have multiple B entities, in one case if I want to get all B's of some certain A's, I might do it with a simple left join
select A.id aid,B.id bid from A
left join B on B.aid = A.id
where A.id = 1
and it will return a result set like
aid bid
1 1
1 2
1 3
As you can see for the first column, all those 1's are kinda duplicates. Is it possible to modify the SQL statement to let him return a result like
aid bid
1 1,2,3
in other words to link all the bid's together as one entity?
Also what if there's another table C, and each A can have multiple C's, how to I make the SQL return a result set like
aid bid cid
1 1,2,3 1,2
instead of
aid bid cid
1 1 1
1 2 1
1 3 1
1 1 2
1 2 2
1 3 2
Thank you very much!
What DBMS are you using?
I can't speak for others, but in MySQL, starting from 4.1, you can use GROUP_CONCAT
http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat
EG:
select A.id aid, GROUP_CONCAT(DISTINCT B.id) bid from A
left join B on B.aid = A.id
where A.id = 1
GROUP BY a.id
Try using the COALESCE function.
http://www.sqlteam.com/article/using-coalesce-to-build-comma-delimited-string