MSsql update column from joint table - sql

I have 2 tables ex. TABLE1 and TABLE2
TABLE1 TABLE2
ID | SIZE | VALUE ID | SIZE | SCORE
1 | LOW | 1.0 1 | MID | 3232
2 | MID | 3.0 2 | MID | 2321
3 | HIGH | 5.0 3 | HIGH | 3232
what i want is to update TABLE2.SCORE so the values will be TABLE1.value column and the join to be SIZE.
OUTPUT:
ID | SIZE | SCORE
1 | MID | 3.0
2 | MID | 3.0
3 | HIGH | 5.0
I tried:
Update Table2 set SCORE=(select top(1) VALUE from TABLE1 join TABLE2 on table1.size=table2.size ) however this does not work I get this result:
OUTPUT:
ID | SIZE | SCORE
1 | MID | 3.0
2 | MID | 3.0
3 | HIGH | 3.0 <---- wrong

Try this
DECLARE #TABLE1 AS TABLE(ID INT , SIZE VARCHAR(10) , VALUE decimal(2,1))
INSERT INTO #TABLE1
SELECT 1 , 'LOW' , 1.0 UNION ALL
SELECT 2 , 'MID' , 3.0 UNION ALL
SELECT 3 , 'HIGH' , 5.0
DECLARE #TABLE2 AS TABLE(ID INT , SIZE VARCHAR(10) , SCORE INT)
INSERT INTO #TABLE2
SELECT 1 , 'MID' , 3232 UNION ALL
SELECT 2 , 'MID' , 2321 UNION ALL
SELECT 3 , 'HIGH' , 3232
SELECT * FROM #TABLE2
UPDATE t2
SET SCORE=t1.VALUE
FROM #TABLE2 t2 inner join #TABLE1 t1 On t1.SIZE=t2.SIZE
SELECT ID,SIZE, CAST(SCORE AS DECIMAL(2,1)) AS SCORE
FROM #TABLE2
Demo result : http://rextester.com/VFF59681

You can use a JOIN in the UPDATE:
update t2
set t2.score = t1.score
from table2 t2 join
table1 t1
on t2.size = t1.size;
You can also follow your pattern by using a correlated subquery:
update table2
set t2.score = (select t1.score from table1 t1 where t1.size = table2.size);
There is no need for another JOIN in the subquery.

update a
set a.score=b.score
from table2 a join table1 b on a.id=b.id

You don't need to do the JOIN in subquery you can directly express it as :
update table2
set score = (select top (1) t1.score from table1 t1 where t1.size = table2.size);

You can achieve it like this:
update table2
set table2.SCORE = table1.VALUE
from table2
join table1
on table2.SIZE = table1.SIZE
However, to avoid problems, you will need to make sure table1.SIZE is unique.

Related

SQL query returning all rows from Table2

I am trying to join 2 tables and return data if the Table1.codeId is presented on Table2 OR if Table1.codeId = 0. However, It retrieves the data from Table2.
Table1 {
name nvarchar,
codeId int
}
| name | codeId |
|--------|--------|
| Bob | 1 |
| Bob | 2 |
| Chris | 0 |
Table2 {
id int,
codeName nvarchar
}
| id | codeName |
|------|----------|
| 1 | Engineer |
| 2 | Doctor |
| 3 | Dentist |
| 4 | Pilot |
| 5 | Mechanic |
SELECT t1.name, t2.codeName
FROM dbo.Table1 t1, dbo.Table2 t2
WHERE (t1.codeId = t2.id OR t1.codeId = 0)
Expected result:
Bob, 1
John, 2
Chris, 0
You are not required to use Join at all for such condition.
You can use subquery as following, it return same result as your expectation
select name,codeid from table1 where codeid in (select id from table2)
or codeid=0
What if you do it in two separates queries ?
Looking at the outcome, the problem must come from the WHERE clause. The OR seem to always be triggered.
So maybe splitting could do it
SELECT t1.name, t2.codeName
FROM dbo.Table1 t1, dbo.Table2 t2
WHERE (t1.codeId = t2.id)
SELECT t1.name, t2.codeName
FROM dbo.Table1 t1, dbo.Table2 t2
WHERE (t1.codeId = 0)
You can use a left join. Use it to select where there is a code match in Table2 or the code_id is 0.
create table Table1
(
name nvarchar(50),
codeId int
)
create table Table2
(
id int,
codeName nvarchar(50)
)
insert into Table1
VALUES
('Bob', 1),
('John', 2),
('Chris', 0),
('Tom', -1)
-- This should be excluded .. since -1 code doesn't exist in Table2
insert into Table2
VALUES
(1, 'Engineer'),
(2, 'Doctor'),
(3, 'Dentist'),
(4, 'Pilot'),
(5, 'Mechanic')
SELECT t1.name, t1.codeId
FROM dbo.Table1 t1
LEFT JOIN dbo.Table2 t2 ON t1.codeId = t2.id
WHERE t2.id is not NULL or t1.codeId = 0
You have to use left outer join.
please find below query
Select codeid,name
FROM Table1
LEFT OUTER JOIN Table2
ON Table1.codeId=Table2.id;

query select equaled data on three columns of table with four columns and ignore one

I have table have four columns like (right ,left ,up ,down) I want to build query that show equaled data on three of the four columns;
example:
| id | right | left | up | down |
|:---|:------:|:-----:|:------:| -----:|
| 1 | street |hospital|coffee |building|
| 2 | house |hospital|coffee |building|
| 3 | road | bus |coffee |sign |
| 4 | house |hospital|coffee |sign |
| 5 | car |road |coffee |sign |
the result should be like:
id
right
left
up
down
1
street
hospital
coffee
building
2
house
hospital
coffee
building
id number 3 and 5 not included because every column should equal it's self
is that query correct
select t.* from test_table t where
(t.right,t.left,t.up) in (select t.right,t.left,t.up from test_table t group by t.right,t.left,t.up having count(*)>1)
or (t.right,t.left,t.down) in (select t.right,t.left,t.down from test_table t group by t.right,t.left,t.down having count(*)>1)
or (t.right,t.up,t.down) in (select t.right,t.up,t.down from test_table t group by t.right,t.up,t.down having count(*)>1)
or (t.left,t.up,t.down) in (select t.left,t.up,t.down from test_table t group by t.left,t.up,t.down having count(*)>1)
and t.mud_id=285 order by t.right,t.left,t.up,t.down ;
if it correct it's go in loop without result for more than 10m waiting
if not
please what is the correct query to get the result
Since there are some assumptions to be made on how how to order and/or organize the results, you may use the query below to identify each matching pair.
DECLARE #T TABLE(ID INT, [right] VARCHAR(20), [left] varchar(20), up
varchar(20), down varchar(20))
INSERT INTO #T VALUES
(1,'street','hospital','coffee','building'),
(2,'house','hospital','coffee','building'),
(3,'road','bus','coffee','sign'),
(4,'house','hospital','coffee','sign'),
(5,'car','road','coffee','sign'),
(6,'street','road','coffee','sign')
SELECT
T1.ID AS MatchID1,
T2.ID AS MatchID2
FROM
#T T1
INNER JOIN #T T2 ON T1.ID <> T2.ID
GROUP BY
T1.ID, T2.ID
HAVING
MAX(CASE WHEN T1.[right] = T2.[right] THEN 1 ELSE 0 END +
CASE WHEN T1.[left] = T2.[left] THEN 1 ELSE 0 END +
CASE WHEN T1.up = T2.up THEN 1 ELSE 0 END +
CASE WHEN T1.down = T2.down THEN 1 ELSE 0 END) = 3
MatchID1 MatchID2
2 1
1 2
4 2
2 4
6 5
5 6
A trick to bring back matches by first occurrence using:
INNER JOIN #T T2 ON T1.ID > T2.ID
MatchID1 MatchID2
1 2
2 4
5 6

SQL Loop and Join

I have a table:
Vers | Rev
3 | A
7 | B
13 | C
And a second table:
Info | Version
aab | 1
adr | 2
bhj | 3
bgt | 4
nnh | 4
ggt | 7
I need to have a table:
Info | Version | Rev
aab | 1 | A
adr | 2 | A
bhj | 3 | A
bgt | 4 | B
nnh | 4 | B
ggt | 7 | B
How do I achieve the final table?
Rev A is for Versions 1-3, Rev B is versions 4-7, Rev C is versions 5-13.
If I were trying to do this with VB Excel, I would add a 1 in a new column. Then get the first Vers value (3) - second Vers value (7) then output 4....
Then I would use some logic If <= new column and >= Vers write Rev.
I don't know how to do this in SQL and I need to!
Try this you can do it by joining tables
select
t2.Info Info
,t2.Version Version
,t1.Rev Rev
from table1 t1,table2 t2
where t2.Version=t1.Vers;
Use outer apply:
select t2.*, t1.rev
from table2 t2 outer apply
(select top (1) t1.*
from table1 t1
where t2.version <= t1.vers
order by t1.vers asc
) t1;
This gets the "next" version in table1 relative to each version in table2.
You can also do this with a subquery:
SELECT *
, (SELECT TOP 1 b.rev
FROM Table1 b
WHERE a.version <= b.vers
ORDER BY b.vers)
FROM Table2 a
Or a third version:
declare #t1 table(V int, R char(1))
insert #t1 values (3,'A'),(7,'B'),(13,'C')
declare #t2 table(I char(3), V int)
insert #t2 values ('aab',1),('adr',2),('bhj',3),('bgt',4),('nnh',4),('ggt',7)
select t2.*, t1.R
from #t2 t2
join #t1 t1 on t1.V>=t2.V and not exists(select * from #t1 t3 where t3.V>=t2.v and t3.V<t1.V)

Getting all the current effective records from a ORACLE table

I have two tables in oracle database
Table 1 say table1 with fields (id, name)
Records e.g.
###############
id | name
1 | Chair
2 | Table
3 | Bed
###############
and Table 2 say table2 with fields (id, table1_id, date, price)
##############################
id |table1_id| date | price
1 | 1 | 2013-09-09 | 500
2 | 1 | 2013-08-09 | 300
3 | 2 | 2013-09-09 | 5100
4 | 2 | 2013-08-09 | 5000
5 | 3 | 2013-09-09 | 10500
################################
What I want to achieve is to retrieve all the latest price of items from table 2
Result of SQL should be like
##############################
id |table1_id| date | price
1 | 1 | 2013-09-09 | 500
3 | 2 | 2013-09-09 | 5100
5 | 3 | 2013-09-09 | 10500
################################
I am able to run in mysql by following query
SELECT t2.id, t1.id, t1.name, t2.date, t2.price
FROM table1 t1 JOIN table2 t2
ON (t1.id = t2.table1_id
AND t2.id = (
SELECT id
FROM table2
WHERE table1_id = t1.id
ORDER BY table2.date DESC
LIMIT 1
));
but it's not working in ORACLE, Here i Need a query which can run on both server with minor modification
You may try this (shoud work in both MySQL and Oracle):
select t2.id, t2.table1_id, t2.dat, t2.price
from table1 t1 join table2 t2 on (t1.id = t2.table1_id)
join (select table1_id, max(dat) max_date
from table2 group by table1_id) tmax
on (tmax.table1_id = t2.table1_id and tmax.max_date = t2.dat);
This query may return several rows for the same table1_id and date if there are several prices in table2, like this:
##############################
id |table1_id| date | price
1 | 1 | 2013-09-09 | 500
2 | 1 | 2013-09-09 | 300
It's possible to change the query to retrieve only 1 row for each table1_id, but there should be some additional requirements (which row to choose in the above example)
if it doesn't matter then you may try this:
select max(t2.id) as id, t2.table1_id, t2.dat, max(t2.price) as price
from table1 t1 join table2 t2 on (t1.id = t2.table1_id)
join (select table1_id, max(dat) max_date
from table2 group by table1_id) tmax
on (tmax.table1_id = t2.table1_id and tmax.max_date = t2.dat)
group by t2.table1_id, t2.dat;
You can try this using GROUP BY instead, since you're not retrieving the product name from table1 except the product id (which is already in table2)
SELECT id,table1_id,max(date),price
FROM table2
GROUP BY id,table1_id,price
this is what you want :
select t2.id,t2.table1_id,t1.name,t2.pricedate,t2.price
from table1 t1
join
(
select id,table1_id, pricedate,price, row_number() over (partition by table1_id order by pricedate desc) rn
from table2
) t2
on t1.id = t2.table1_id
where t2.rn = 1

Update based on previous value SQL SERVER 2005

I need to Update these NULL Values:
PK | CODE
---+-------
1 | 20
2 | NULL
3 | NULL
4 | 30
5 | NULL
6 | NULL
7 | NULL
8 | 40
9 | NULL
Like this:
PK | CODE
-----+------------
1 | 20
2 | 20
3 | 20
4 | 30
5 | 30
6 | 30
7 | 30
8 | 40
9 | 40
It should always be based on the last minimum value.
I have tried the code below, but it just updates the first row before the one who had value at the beginning.
QUERY
UPDATE TT
SET CODE = (SELECT CODE
FROM #TSPV_TEMP T2 with(nolock)
WHERE T2.KEY = (tt.KEY -1))
FROM #TSPV_TEMP TT with (nolock)
WHERE tt.CODE IS NULL
You can do this as:
UPDATE TT
SET CODE = (SELECT TOP 1 CODE
FROM #TSPV_TEMP T2 with(nolock)
WHERE T2.KEY < tt.KEY AND
CODE IS NOT NULL
ORDER BY KEY DESC
)
FROM #TSPV_TEMP TT with (nolock)
where tt.CODE IS NULL;
Note the differences in the subquery. This looks for the previous non-NULL value for CODE for the update.
update tbl
set code =
(select code
from tbl x
where x.pk = (select max(y.pk)
from tbl y
where y.pk < tbl.pk
and code is not null))
where code is null;
Fiddle:
http://sqlfiddle.com/#!3/3803d/1/0
Another way using a derived table which for every pk with a null code contains the maximum lesser pk with a non-null code.
update t1
set t1.code = t3.code
from tt t1 join
(select t1.pk, max(t2.pk) max_pk
from tt t1
join tt t2 on t1.pk > t2.pk
and t2.code is not null
and t1.code is null
group by t1.pk) t2 on t2.pk = t1.pk
join tt t3 on t3.pk = t2.max_pk