SQL Server Update column comparing cross row's value - sql

I have requirement to update column3 of following table by cross checking the value of value2 with next row of value1
If equal then value3 = value1*value2 and if not value3 = value1
CREATE TABLE #tmpValue1(id INT IDENTITY(1,1), value1 FLOAT, value2 FLOAT, value3 FLOAT)
INSERT INTO #tmpValue1(value1, value2) VALUES
(1, 2), (2,3), (3,4), (4,5),(6,7),(7,8),(8,9)
Table #tmpValue1 will be as:
id value1 value2 value3 (expected output)
1 1 2 1
2 2 3 4
3 3 4 9
4 4 5 16
5 6 7 6
6 7 8 49
7 8 9 64
Above, in value3 updated with 1 in first because 2 of Value2 row first is comparing to 2 of value1 of row second so it will start updating with second.
Note: Value1 and Value2 is just sample and is real it can be different.

We can simply do it by using LEFT JOIN as below:
UPDATE t1 SET t1.value3 = (ISNULL(t2.value2,1) * t1.value1)
FROM #tmpValue1 t1
LEFT JOIN #tmpValue1 t2 ON t1.id = t2.id+1
AND t1.value1 = t2.value2
We should use id which is identity column and is beneficial for performing such an operation.

You can use LAG... though your expected output seems to have some errors in it.
select
ID,
Value1,
Value2,
case
when lag(value2) over (order by ID) = value1 then lag(value2) over (order by ID) * value1
else value1 end as Value3
from #tmpValue1
RESULTS
ID Value1 Value2 Value3
1 1 2 1
2 2 3 4
3 3 4 9
4 4 5 16
5 6 7 6
6 7 8 49
7 8 9 64

Related

Map column values in SQL

I have a table named table1, with one column named col1, which takes value in range 1-9.
table1
col1
1
9
7
2
4
6
1
9
3
5
Now I want to add another column which maps values in col1 to another value given in a map.
1 -> A, 2 -> B, 3 -> C, 4 -> D, 5 -> E, 6 -> F, 7 -> G, 8 -> H, 9 -> I
I want results to look like below.
col1 col2
1 A
9 I
7 G
2 B
4 D
6 F
1 A
9 I
3 C
5 E
My approach is to create a new table with mapping and then do a inner join.
CREATE TABLE map (
col1 int,
col2 varchar
);
INSERT INTO map
(col1, col2)
VALUES
(1,'A'),(2,'B'),(3,'C'),(4,'D'),(5,'E'),(6,'F'),(7,'G'),(8,'H'),(9,'I');
SELECT table1.col1, map.col2
FROM table1 INNER JOIN map ON table1.col1 = map.col1
Is this efficient approach, are there better methods than this?
Use case statement:
Update t
Update new_column =
Case
WHEN col1 = 1 THEN 'A'
WHEN col1 = 2 THEN 'B'
WHEN col1 = 3 THEN 'C'
WHEN col1 = 4 THEN 'D'
WHEN col1 = 5 THEN 'E'
WHEN col1 = 6 THEN 'F'
WHEN col1 = 7 THEN 'G'
WHEN col1 = 8 THEN 'H'
WHEN col1 = 9 THEN 'I'
END
FROM table1 t
Although creating map table can be a good idea, assume you need to fill the map table with query. Then case statement is useful.
CASE col1
WHEN 1 THEN 'A'
WHEN 2 THEN 'B'
WHEN 3 THEN 'C'
WHEN 4 THEN 'D'
-- And so on
END

SQL: Update with minimum value from maximum value

I am struggling to update a column in myTable via VB and OleDB.
myTable:
myGroup Value1 Value2
A 20 5
B 15 3
A 19 4
A 20 6
C 10 2
B 14 4
C 11 7
I want to update column value3 with value2 where value2 is lowest when value1 is highest in group.
I have this:
SELECT myGroup ,MAX(value1), MIN(value2)
FROM myTable
GROUP BY myGroup
I get this:
myGroup Value1 Value2
A 20 4
B 15 3
C 11 2
But I need this:
myGroup Value1 Value2
A 20 5
B 15 3
C 11 7
I need something like "UPDATE mytable SET Value3 = MIN(value2) WHERE MAX(value1) GROUP BY myGroup"
myTabel should be like:
myGroup Value1 Value2 Value3
A 20 5 5
B 15 3 3
A 19 4 5
A 20 6 5
C 10 2 7
B 14 4 3
C 11 7 7
Any help please.
select t.myGroup as myGroup ,value1,min(t.value2) as min2
from stack t
join (select myGroup,max(value1) as max_value1
from stack
group by myGroup) max1_table
on t.myGroup=max1_table.myGroup and t.value1=max1_table.max_value1
group by myGroup,value1
One method is a correlated subquery. Something like this:
select t.*,
(select t2.value2
from t t2
where t2.mygroup = t.mygroup
order by value1 desc, value2 asc
fetch first 1 row only
) as value3
from t;
This uses ANSI/ISO syntax. The specific syntax might vary for your database.
This can also be expressed using the standard function first_value():
select t.*,
first_value(value2) over (partition by mygroup order by value1 desc, value2 asc) as value3
from t;
You might use a query like :
SELECT t1.myGroup, t1.value1, t2.value2 as value3
FROM myTable t1
LEFT JOIN
(
SELECT myGroup, Value1, MIN(VALUE2) AS value2
FROM myTable
WHERE (myGroup, Value1) in
(
SELECT myGroup , MAX(value1)
FROM myTable
GROUP BY myGroup
)
GROUP BY myGroup, Value1) t2
ON ( t1.myGroup = t2.myGroup );
myGroup Value1 Value3
------- ------ ------
A 20 5
B 15 3
A 19 5
A 20 5
C 10 7
B 14 3
C 11 7
Rextester Demo for Select
and with respect to the above SELECT statement, the UPDATE statement might be :
UPDATE myTable t3
SET t3.Value2 =
( SELECT q.value3 FROM
(
SELECT t1.myGroup, t1.value1, t1.value2, t2.value2 as value3
FROM myTable t1
LEFT JOIN
(
SELECT myGroup, Value1, MIN(VALUE2) AS value2
FROM myTable
WHERE (myGroup, Value1) in
(
SELECT myGroup , MAX(value1)
FROM myTable
GROUP BY myGroup
)
GROUP BY myGroup, Value1) t2
ON ( t1.myGroup = t2.myGroup )
) q
WHERE q.myGroup = t3.myGroup
AND q.value1 = t3.value1
AND q.value2 = t3.value2
);
Rextester Demo for Update

Conditional Sort In Groups

Please consider this result set:
Name Value1 Value2 Value3
---------------------------------------
ccc 1 2 3
aaa 3 4 3
bbb 2 8 5
Group 1 2 1 3
rrr 1 2 5
mmm 3 4 4
nnn 3 2 1
eee 2 6 5
Group 2 2 4 4
...
As you see the record in each group don't sorted in alphabetically order. How I can sort record in each group alphabetically?
The desired result set is:
Name Value1 Value2 Value3
---------------------------------------
aaa 3 4 3
bbb 2 8 5
ccc 1 2 3
Group 1 2 1 3
eee 2 6 5
mmm 3 4 4
nnn 3 2 1
rrr 1 2 5
Group 2 2 4 4
...
EDIT 1)
Code for generat base result set:
DECLARE #tbl AS Table
(
Name NVARCHAR(50),
Value1 DECIMAL(5,2),
Value2 DECIMAL(5,2),
Value3 DECIMAL(5,2)
)
INSERT INTO #tbl VALUES('ccc',1,2,3)
INSERT INTO #tbl VALUES('aaa',3,4,3)
INSERT INTO #tbl VALUES('bbb',2,8,5)
INSERT INTO #tbl VALUES('Group 1',2,1,3)
INSERT INTO #tbl VALUES('rrr',1,2,5)
INSERT INTO #tbl VALUES('mmm',3,4,4)
INSERT INTO #tbl VALUES('nnn',3,2,1)
INSERT INTO #tbl VALUES('Group 2',2,4,4)
select * from #tbl
Try this:
select * from (
select Name, value1, value2, value3,
case when Name like 'group%' then SUM(Groups) over (order by (select null) rows between unbounded preceding and current row) - 1
else SUM(Groups) over (order by (select null) rows between unbounded preceding and current row) end [groupingCol],
groups
from (
select *,
case when Name like 'group%' then 1 else 0 end [Groups] from #tbl
) a
) b order by groupingCol, Groups, name

how to get rows which have max value2 when value1 is equal using django queryset

for example
rowid value1 value2
1 1 2
2 1 3
3 2 4
then select (1,1,3) and (3,2,4) because row1 and row2 have the same value1, and value2 of row2 is bigger than value2 of row1
thank you!
In sql this is a simple aggregation query using group by and min()/max()
select
min(rowid) as rowid
, value1
, max(value2) as value2
from t
group by value1

column update in sequence

I have a table that contains 3 columns as below:
col1 col2 col3
---- ---- ----
1 1 null
2 2 null
3 3 null
4 1 null
5 1 null
6 1 null
7 2 null
ETC
I need to update a third column in the same table as follows:
col1 col2 col3
---- ---- ----
1 1 1
2 2 1
3 3 1
4 1 2
5 1 3
6 1 4
7 2 4
The logic behind the update is that each time the 2nd column contains a 1 in it, the third has to increment. The first column is just a sequential integer column.
You can use the row_number analytical function to number the rows with col2 = 1 sequentially and then use a subquery to find to closest value with a lower col1 for the other rows.
So given a test table like this:
create table t (c1 int, c2 int, c3 int);
insert t (c1, c2) values
(1, 1),
(2, 2),
(3, 3),
(4, 1),
(5, 1),
(6, 1),
(7, 2);
A query like this:
;with cte as (
select t.c1, t.c2, x.c3
from t
left join (
select c1, c2, row_number() over (partition by c2 order by c1) c3
from t
where c2 = 1
) x on t.c1 = x.c1
)
update t
set t.c3 = coalesce(cte1.c3,(select max(cte2.c3) from cte cte2 where cte2.c1 < cte1.c1))
from cte cte1
where t.c1 = cte1.c1
Will give the following result:
c1 c2 c3
1 1 1
2 2 1
3 3 1
4 1 2
5 1 3
6 1 4
7 2 4
Another, possibly faster, way to do this would be:
update t1 set c3 = (select count(*) from t where c2 = 1 and c1 <= t1.c1) from t t1