Update Table Beginning At Record One SQL Server - sql

I am trying to update a table with records from another table. Whenever I use the insert into statement, I find that the records are simply appended. Instead, I want the records to be inserted from the top of the table. What is the easiest way to do this? I am thin king I could use a update statement, but that means I will have to join the tables. One of the tables(the one I am pulling records from) has only one column. As such, I would have to include another column to do the join.I am trying not to make it so complicated. If there is a simplier way, please let me know.
Sample:
Table One
Col1
1
2
3
4
Table 2
Col1 Col2
a
b
c
d
I want to move column 1 from table 1 to column 2 in table 2 such that table 2 will be:
Table 2
Col1 Col2
a 1
b 2
c 3
d 4

You can do the update using row_number(), but the rows will be assigned in an indeterminate order:
with toupdate as (
select t2.*, row_number() over (select NULL)) as seqnum
from table2 t2
),
t1 as (
select t1.*, row_numbrer() over (select NULL)) as seqnum
from table1 t1
)
update toupdate
set col2 = t1.col1
from toupdate join
t1
on toupdate.seqnum = t1.seqnum;
Note: if you have an ordering in mind, then use the appropriate order by in the partition clauses.

Unless you explicity define an ORDER BY clause in your SELECT statements, your result set will be completely arbitrary. This is in line with how any RDBMS should operate. You should consider including a timestamp at the time of insertion to identify the latest rows.

Related

What is the SQL standard for updating one row when multiple are matched with an UPDATE+FROM

With the following SQL:
CREATE TABLE tableA (
id int primary key,
local_id int not null
);
INSERT INTO tableA (id,local_id) VALUES
(122,0),(123,0),(124,0);
UPDATE tableA SET tableA.local_id = tableB.id
FROM (
SELECT 1 AS id, 1 AS rn
UNION
SELECT 3 AS id, 1 AS rn
UNION
SELECT 2 AS id, 1 AS rn
) AS tableB
WHERE tableA.id = 123 AND tableB.rn = 1;
This SQL matches only 1 row in tableA and 3 rows in tableB.
What is the rule for updating local_id in this case? without an ORDER BY inside the inner FROM, it seems that it picks the highest INT, but I doubt that behavior is explicit? (In this case it is 3).
Is this behavior defined somewhere in the SQL standard?
If I set ORDER BY id DESC inside the parenthesis, am I certain it will always pick the top row?
This is a simplified problem, usually, more than 1 row is updated in tableA, so setting a TOP/LIMIT is not going to cut it.
Current query give just an error. You can update multiple rows with 1 value from target table. But you can't update 1 row with multiple values from target. So just make target table unique. As you mentioned, get max value.

How to select rows without duplicates when one column is different?

This is my table with 4 columns:
a b e d
a f c d
I want to get all 1st and 4th columns, so that the first two rows will be merged into one row in the example, since they are the same:
a d
a d
When I use the command:
select column1, column4 from my_table;
Would this automatically remove duplicates? If not, how to get distinct rows with only the 1 and 4 columns?
little confusing question.
Do you want to delete duplicate data or you want to just select non-duplicate data?
If you want to delete duplicate data then it will be like this -
insert overwrite my_table
select * from my_table
join (
Select col1||col2||col3||col4 key, row_number() over (partition by col1,col4 order by col1 ) as rn
from my_table) rs on rs.key = col1||col2||col3||col4 and rs.rn=1
If you want to select the unique col1 and col4 and dont want to change underlying data, you can simply fire
select distinct column1, column4 from my_table;

Exclude rows that have same value in two different columns

I have a table which has 2 columns that sometimes have the same values. I want to know how to exclude the rows where the value of column1 is equal to a value in column2.
EXAMPLE:
COL1 | COL2
1 -------- 7
2 -------- 8
3 -------- 2
4 -------- 5
5 -------- 9
Here I would exclude rows 2 and 5.
Thanks
select
*
from table
where col1 not in (
select
column2
from table
)
Something like this should work :
SELECT *
FROM yourtable
WHERE COL1 NOT IN (SELECT COL2
FROM yourtable)
I tend to avoid using IN for long lists of values, as it performs poorly on some database systems. The following selects all values from col1 that are not present in col2:
SELECT col1
FROM
yourtable t1
LEFT JOIN
yourtable t2
ON
t1.col1 = t2.col2
WHERE
t2.col2 IS NULL
Why does it work? Well, normally the join operator will link together rows that have the same value. Left join will keep some rows that are mismatched though (and it's those we want). The left join takes the table on the left (t1) and uses it as the reference table, and starts associating rows from the table on the right (after the word JOIN, in this case t2). If the col1 value has a matching value in col2 then the row will be fully populated with values for each. If the value from col1 has no matching value from col2, the col2 cell on the resulting row is blank/null. Because we hence want to know only those values that aren't matched, we say "where col2 is null"
The other trick with getting to grips with this is in understanding that the same table can appear twice in a query. We give it a different alias each time we use it so we can tell them apart. You could conceive it as virtually making a copy of the table, before it links them together
Use EXCEPT together with a correlated sub-query - as shown below.
Read up on EXCEPT here: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/set-operators-except-and-intersect-transact-sql
SELECT *
FROM TEST
EXCEPT
SELECT *
FROM TEST
WHERE COL1 IN (
SELECT COL2
FROM TEST
)
not sure, but maybe...
SELECT t1.*
FROM my_table AS t1
LEFT JOIN my_table AS t2
ON t2.col_b = t1.col_a
WHERE t2.col_b IS NULL

Sort column values to match order of values in another table column

Let's say I have table like this:
Column1 Column2
C 2
B 1
A 3
I need to exchange values in the second column to get this:
Column1 Column2
C 3
B 2
A 1
The goal is only for numeric column to have values sorted to follow alphabetical order on another column. The actual table has multiple columns and column 1 is people's name, while column 2 two is rank for rendering column 1 values in UI.
What is the most optimal way to do this?
I am doing this from C# code, on SQL server and have to use System.Data.SqlClient.SqlCommand because of transaction. But maybe it's not important if this can all be done from SQL.
Thank you!
So you need to update Column2 with the row-number according toColumn1?
You can use ROW_NUMBER and a CTE:
WITH CTE AS
(
SELECT Column1, Column2, RN = ROW_NUMBER() OVER (ORDER BY Column1)
FROM MyTable
)
UPDATE CTE SET Column2 = RN;
This updates the table MyTable and works because the CTE selects a single table. If it contains more than one table you have to JOIN the UPDATE with the CTE.
Demo

ROW_NUMBER() Set Null to anything beside Min

So I have this basic setup:
Declare #temp Table(t1 varchar(1)
,t2 int)
insert into #temp (t1,t2)
Values
('a','1')
,('a','2')
,('a','3')
,('a','4')
,('a',null)
select t1,t2,ROW_NUMBER() OVER ( PARTITION BY T1 ORDER BY t2) 'rnk'
from #temp
The problem is, the value that is Null get ranked the highest. What I am trying to do is set the first non zero/null value to the highest rank(lowest number) current output is:
t1 t2 rnk
a NULL 1
a 0 2
a 1 3
a 2 4
a 3 5
I want
t1 t2 rnk
a NULL 4/5 --either or
a 0 4/5
a 1 1
a 2 2
a 3 3
I know i can do this with subquerys but the problem is to get t2, is a 200 character case statement that i really don't want to copy and paste all over, once to calculate, then one to order by and such. I am seeing a Query to get the values, inside a query to get the rank,inside a query to only pull those ranked 1, which is 3 deep and i don't know like that. note i know it say oracle and i am sure at least one person will mark me down since this is in SQL server, BUT, the actual code is in oracle, i am just much better in SQL server and its easy to translate unless Oracle has some magic function that makes this easier.
You can use two keys for the order by. The following is compatible with both SQL Server and Oracle:
select t1, t2,
ROW_NUMBER() OVER (PARTITION BY T1
ORDER BY (CASE WHEN t2 IS NOT NULL OR T2 <> 0 THEN 0 ELSE 1 END),
t2
) as rnk
from #temp;
Oracle supports NULLS LAST, which makes it easier: ORDER BY t2 NULLS LAST.
Another option would be to use the ISNULL function to set it to the max value of the type on null values. So if t2 is an integer it would be:
select t1,t2,ROW_NUMBER() OVER ( PARTITION BY T1 ORDER BY ISNULL(t2,2147483647)) 'rnk'
from #temp
This would prevent you from having to use t2 (your big case statement) in your expression more than once.
I believe Oracle uses NVL instead of ISNULL.