set value using a conditional of a subquery - sql

Sorry if I am not explaining my issue the best, but basically I have two tables.
Table A has a reference column to table B. On table B there is column X where for each referenced row, there is an unreferenced row with that same value of column X (table B has double the rows of table A). I want to update the reference on table A to be the row of table B that is not currently referenced of the two rows that have the same value on column X.
In pseudo code...
update tableA
set refCol = (select tableB.refCol
from tableB
where colX = (select colX
from tableB
where tableB.refCol = tableA.refCol)
and tableB.refCol != tableA.refCol)
The innermost query returns two rows, the outer query returns one row
sample tables:
Table A
refCol
1
3
Table B
refCol
colX
1
hello
2
hello
3
hi
4
hi
expected output:
Table A
refCol
2
4
Any help would be much appreciated.

Refer it below working example
create table #tableA(
id int)
create table #tableB(
id int,
name varchar(10)
)
insert into #tableA values(1)
insert into #tableA values(3)
insert into #tableA values(5)
insert into #tableA values(6)
insert into #tableA values(7)
insert into #tableA values(8)
insert into #tableB values (1,'A')
insert into #tableB values (2,'A')
insert into #tableB values (3,'C')
insert into #tableB values (4,'C')
select * from #tableA
select * from #tableB
update aa set aa.id=ab.id from #tableA aa inner join (
select b.id,b.name,a.id as ta from (
select B.* from #tableB b left join #tableA a on a.id=b.id where a.id is null)b
inner join (
select b.* from #tableA a inner join #tableB b on a.id=b.id)a on a.name=b.name)ab on aa.id=ab.ta

Related

Insert or update multiples rows

I have two tables where TableA has latest data and TableB has some old data. I want to update TableB's data if it matches id with TableA and if doesn't match insert new row in TableB.
I got a solution from stackOverflow
begin tran
if exists (select * from t with (updlock,serializable) where pk = #id)
begin
update t set hitCount = hitCount+1
where pk = #id
end
else
begin
insert t (pk, hitCount)
values (#id, 1)
end
commit tran
But it seems I need to pass #id each time, may be I am not getting it in the correct way. I have hundreds of row to update/insert from tableA.
Think relationally.
SQL Server always operates sets. A single row is just a set of 1 row.
Here is a simple example of two step update - insert operations
create table #tableA(id int, [year] int, updated_value int)
insert #tableA(id,[year],updated_value)
values
(1,1990,85),
(2,1991,70),
(3,1992,80)
create table #tableB(id int, [year] int, score int)
insert #tableB(id,[year],score)
values
(1,1990,50),
(4,1995,20)
update #tableA set
updated_value=b.score
from #tableA a
inner join #tableB b on a.id=b.id --inner is important
insert #tableA(id,[year],updated_value)
select b.id,b.[year],b.score
from #tableB b
left join #tableA a on a.id=b.id --left is important
where a.id is null -- and this line too
select * from #tableA
If you wish you can combine update and insert in a single merge operation.
merge #tableA as tgt
using #tableB as src
on src.id=tgt.id
when matched then
update set updated_value=src.score
when not matched then
insert(id,[year],updated_value)
values(id,[year],score)
; -- semicoloumn is required
select * from #tableA

JOIN tables based on 6 or 7 digits key in 1st table with 7 digits key in second table by using CASE and MAX function

Table 1:
Id1 Data1
123123 David
123124 Jan
1231344 Juro
1234126 Marco
Table 2:
Id2 Data2
1231230 Info 1
1231231 Info 2
1231232 Info 3
1231240 Info 4
1231241 Info 5
1231242 Info 6
Each id from Table 1 can have 1 or more matches in Table 2 based on first 6 digits.
For example 123123 from Table 1 matches 1231230, 1231231 and 1231232 in Table 2.
I'm trying to create join to match maximum id2 from Table 2 based on id1 from Table 1.
I would just join using LIKE:
SELECT
tb1.id1,
tb1.data1
MAX(tb2.[id2]) AS id2
FROM [dbo].[table1] tb1
LEFT JOIN [dbo].[table2] tb2
ON tb2.[id2] LIKE CONCAT(tb1.[id1], '%')
GROUP BY
tb1.id1,
tb1.data1
ORDER BY
tb1.id1 DESC;
This approach might still leave open the possibility of using an index on the second table. In any case, it is slightly easier to read than your version.
This is working solution:
SELECT tb1.*,
MAX(tb2.[id2]) as id2
FROM [dbo].[table1] tb1
LEFT JOIN [dbo].[table2] tb2
ON CASE
WHEN LEN(tb1.[id1]) = 7 and tb1.[id1] = tb2.[id2] THEN 1
WHEN LEN(tb1.[id1]) = 6 and tb1.[id1] = SUBSTRING(tb2.[id2],1,6) THEN 1
ELSE 0
END = 1
GROUP BY tb1.id1
,tb1.data1
ORDER BY tb1.id1 desc
You can try this as well:
Declare #t table (id1 varchar(50) , data1 varchar(50))
insert into #t values (123123,'David')
insert into #t values (123124,'Jan')
insert into #t values (1231344,'Juro')
Declare #t1 table (id2 varchar(50) , data2 varchar(50))
insert into #t1 values (1231230,'Info 1')
insert into #t1 values (1231231,'Info 2')
insert into #t1 values (1231232,'Info 3')
insert into #t1 values (1231240,'Info 4')
insert into #t1 values (1231241,'Info 5')
insert into #t1 values (1231242,'Info 6')
select * from #t a JOIN #t1 B
on b.id2 like '%' + a.id1 + '%'

Need to fetch records from one table which is not present in another one table

I have two tables, one table has three columns another one has two columns. I need to fetch records from Table1 which is not present in Table2. For example
DECLARE #Table1 TABLE (C1 INT, C2 INT, C3 INT)
INSERT INTO #Table1 VALUES(1,1,1)
INSERT INTO #Table1 VALUES(1,2,2)
INSERT INTO #Table1 VALUES(1,3,3)
INSERT INTO #Table1 VALUES(2,1,4)
DECLARE #Table2 TABLE (C1 INT, C2 INT)
INSERT INTO #Table2 VALUES(1,1)
INSERT INTO #Table2 VALUES(1,2)
I need the result as shown below
C1 C2 C3
--------
1 3 3
2 1 4
This should work:
SELECT Table1.*
FROM Table1
LEFT OUTER JOIN Table2
ON Table1.C1 = Table2.C1
AND Table1.C2 = Table2.C2
WHERE Table2.C1 IS NULL
AND Table2.C2 IS NULL
Please try this -
SELECT t1.*
from table1 t1
where not exists (select null from table2 t2
where t1.c1=t2.c1
and t1.c2=t2.c2);

How to update table by closet match of two table columns and replace wiht one value in one table using sql?

I have two tables with the following values
Table A Table B
PartNo PartNo
3AL9723AA 3AL9723AAA01
3AL7881BA 3AL7881BAA02
1AB5677FC 1AB5677FCD02
Now I want to compare these two PartNo values upto 9 characters and if the 9 characters match then replace the PartNo value in Table B with PartNo in Table A and neglect or remove last three characters,
Please can anyone help me to write the query for this problem.
In MySQL:
UPDATE tableA a, tableB b
SET b.PartNo=a.PartNo
WHERE LEFT(a.PartNo, 9) = LEFT(b.PartNo, 9);
In MS SQL:
-- Setup
declare #TableA table(PartNo varchar(20))
declare #TableB table(PartNo varchar(20))
insert #TableA
values
('3AL9723AA'),
('3AL7881BA'),
('1AB5677FC')
insert #TableB
values
('3AL9723AAA01'),
('3AL7881BAA02'),
('1AB5677FCD02')
-- Query
update b
set PartNo = a.PartNo
from #TableA a
join #TableB b on
left(a.PartNo, 9) = left(b.PartNo, 9)
-- Result check
select *
from #TableB

SQL query: finding a gap in a primary key

How can I write a single select statement that does the following:
I have an integer column in my table and i want to find the minimum available (non-used) value in that column where the value is below 1000 and also where the value does not exist in TableB Column1
Thanks
Similar to LukeH's answer but it does what you asked for:
SELECT MIN(a.your_column) - 1 AS answer
FROM your_table AS a
LEFT JOIN your_table AS a2
ON a2.your_column = a.your_column - 1
LEFT JOIN tableB AS b
ON a.your_column = b.column1
WHERE a.your_column < 1000
AND b.column1 IS NULL
AND a2.your_column IS NULL
Edit:
UNION
SELECT MIN(a.your_column) + 1 AS answer
FROM your_table AS a
LEFT JOIN your_table AS a2
ON a2.your_column = a.your_column + 1
LEFT JOIN tableB AS b
ON a.your_column = b.column1
WHERE a.your_column < 1000
AND b.column1 IS NULL
AND a2.your_column IS NULL
And pick the minumum of the two values.
It still needs checking if the value 1 is available, but if you have a gap between A and B it should find A+1 and B-1 now and you could pick the smallest. Obviously A+1 is the smallest so you can just use the second part...
This results in 7, which I believe would be the correct answer given your criteria
CREATE TABLE #TableA (Value INT)
INSERT #TableA (Value) VALUES (1)
INSERT #TableA (Value) VALUES (2)
INSERT #TableA (Value) VALUES (3)
INSERT #TableA (Value) VALUES (5)
INSERT #TableA (Value) VALUES (6)
INSERT #TableA (Value) VALUES (8)
CREATE TABLE #TableB (Value INT)
INSERT #TableB (Value) VALUES (4)
SELECT MIN(A1.Value) + 1
FROM #TableA A1
LEFT JOIN #TableA A2 ON A2.Value = A1.Value + 1
LEFT JOIN #TableB B1 ON B1.Value = A1.Value + 1
WHERE A2.Value IS NULL
AND B1.Value IS NULL
AND A1.Value < 1000
DROP TABLE #TableA
DROP TABLE #TableB