Moving a cell value to another row based on ID numbers - sql

I am looking to move B to the above row. It can either be placed where the Null value is in Column B or another column can be created. The value of B is linked to value A through an ID. The ID for value B is always X + 2 (the values in the ID column are integers).
I can’t just move the value up because the table I am working with has thousands of rows. It must be linked to the ID’s.
Please let me know if you have any questions. Any assistance is much appreciated. Thank you.
ID
Column A
Column B
X
A
NULL
X+2
NULL
B
Keep in mind I am very new to SQL. Below is what I tried. It created a new column that only contains NULL values.
Select
Column_B
From
Table_Name
Where
Table_Name.ID = Table_Name.ID +2 ) AS Col_B_Value

You can use a conditional subselect for that
UPDATE Table_Name T1
SET Column_B = (Select
Column_B
From
Table_Name
Where
Table_Name.ID = T1.ID +2 )
WHERE Column_B IS NULL
Some databases could have a problem so you can make
UPDATE Table_Name T1
SET Column_B = (Select
T2.Column_B
From
(SELECT ID,Column_B FROM Table_Name) T2
Where
T2.ID = T1.ID +2 )
WHERE Column_B IS NULL

You could just do it with 2 updates statements
UPDATE Table
SET Column B = 'B'
WHERE ID = 'X'
UPDATE Table
SET Column B = NULL
WHERE ID = 'X+2'
If you need to do it in a select statement you could do it with a case statement too
SELECT ID,
Column A,
CASE WHEN ID = X AND Column B = NULL THEN 'B'
ELSE Column B END
FROM Table

Related

SQL Update all rows for one column with a list of values

How can I set all rows of a column by manually typing the values?
My table has 3 rows, I want the column named mycolumn to have 3 values a, b and c (currently those values are NULL):
update mytable set mycolumn = ('a','b','c')
ORA-00907 missing right parenthesis
EDIT: my table is very simple, I have one column ID INT NOT NULL with values 1, 2, 3 and another column mycolumn with all NULL values and I want those values to become 'a' where ID = 1, 'b' where ID=2 etc.
EDIT2: I might have a huge amount of rows, so I want to avoid typing every single ID value where to replace mycolumn. Isn't it possible to match the ID values of 1 to 3 to the values 'a', 'b', 'c' in an automatic way, something like match(ID, ('a','b','c')) perhaps
I just want to replace all values of mycolumn by increasing order of ID. ID being strictly equivalent to what I call a row number in a matrix
EDIT3: I'd like a solution which would work in a general case with all sorts of values, not only the letters of the alphabet given here for simplicity. What if for example my values to replace in mycolumn are ('oefaihfoiashfe', 'fiaohoawdihoiwahopah', 'aefohdfaohdao')? However the ID row numbers will always be a sequence from 1 to N by 1.
Obviously, you should do this in a single update. Like this:
update mytable
set mycolumn = case id when 1 then 'a' when 2 then 'b' when 3 then 'c' end
;
More compact (but also more cryptic, and only works in Oracle, while case expressions are in the SQL standard):
update mytable
set mycolumn = decode(id, 1, 'a', 2, 'b', 3, 'c')
;
Note - this only works if there really are only three rows. If you have many more rows, make sure to add where id in (1, 2, 3) at the end. Otherwise all the OTHER values (in the other rows) will be updated to null!
You can try an update like the one below. This will update 1 > a, 2 > b, 3 > c, 4 > d, etc. When you reach ID 27, since there are no more letters, it will begin at a again and continue down the alphabet.
UPDATE mytable
SET mycolumn = CASE MOD (id, 26)
WHEN 0 THEN 'z'
ELSE CHR (MOD (id, 26) + 96)
END;
Update
To update based on any list of values, you can try an update statement like the one below. If you add a 4th item to the comma delimited list, ID 4 in mytable will be set to whatever you specified as the 4th value.
UPDATE mytable
SET mycolumn =
(SELECT COLUMN_VALUE
FROM (SELECT ROWNUM AS row_num, t.COLUMN_VALUE
FROM TABLE (
sys.odcivarchar2list ('oefaihfoiashfe',
'fiaohoawdihoiwahopah',
'aefohdfaohdao')) t)
WHERE row_num = id);
Hmmm . . . A row can only have one value. Perhaps something like this to assign random values:
update mytable
set mycolumn = (case floor(dbms_random.random * 3)
case 0 then 'a' case 1 then 'b' else 'c'
end)
if you want the 3 rows to have different values a, b and c then you will have to write 3 update statements.
update mytable set mycolumn = 'a' where id = 1;
update mytable set mycolumn = 'b' where id = 2;
update mytable set mycolumn = 'c' where id = 3;

Rename category in the column in SQL Server

Here is the query
select col1
from table
col1 contains these category values:
A
B
C
NULL
How can I rename null category to D?
If you want to make the change permanent
UPDATE table
SET col1 = 'D'
WHERE col1 IS NULL
From then on you can simply query with ...
SELECT col1
FROM table
... to get the desired result.
If there is more than one row having a NULL in col1, you need to filter by a unique key, preferably by the primary key (which every table should have by the way). Let's say you have a table like
id (PK) col1
--- ----
1 'A'
2 'B'
3 'C'
4 NULL
5 NULL
then you can fix it with
UPDATE table SET col1 = 'D' WHERE id = 4;
UPDATE table SET col1 = 'E' WHERE id = 5;
unless you can calculate the new value from another column, e.g.:
UPDATE table
SET col1 = UPPER(LEFT(name, 1))
Try this : ISNULL( ) function is used to replace NULL value with another value
select isnull(col1,'D') as col1
from table
SQL Server uses ISNULL().
SELECT ISNULL(value_to_check, use_this_instead_if_valuetocheck_is_null)
For your code:
select ISNULL(col1, 'D') AS col_name
from table
However, this will happen across the board for this column. You can't use this to make a sequence, like D then E then F. Any NULL value you come across in this column will change to D.

Compare each row values in second table in SQL Server?

I have a scenario where I have to search value of column 1 in first table to see whether it matches some value in another table.
This should continue in a loop until the last row on first table has been compared.
No loops needed. You can do this easily as a set based operation using exists()
select *
from FirstTable
where exists (
select 1
from SecondTable
where FirstTable.Column1 = SecondTable.Column1
);
To find the opposite, where the row in the first table does not have a match based on Column1, you can use not exists()
select *
from FirstTable
where not exists (
select 1
from SecondTable
where FirstTable.Column1 = SecondTable.Column1
);
If you want to identify which rows have a match and don't you can use:
select FirstTable.*
, MatchFound = case when x.Column1 is null then 'No' else 'Yes' end
, x.Column1
from FirstTable
outer apply (
select top 1
*
from SecondTable
where FirstTable.Column1 = SecondTable.Column1
) as x

SQL: Difference between rows

I am trying to find the difference between two numbers corresponding to the same ID, but with two different conditions. For example,
Column A Column B Column C
1234 3 True
1234 5 False
5678 10 True
5678 15 False
So basically i want to find the difference in Column B when column A is the same but Column C is different.
If we can assume
2 rows for a given value in ColumnA
expected result is only 1 row returned per unique colA value
columnC will never be null...
Column B will never match, and if they do, you don't want the record returned.
We can use a self join checking for matches on column A, no matches on column C and so that we don't get a row each for 1234 of 2 and -2.
SELECT Z.ColumnA, Z.B-Y.B
FROM TableName Z
INNER JOIN tableName Y
on Z.ColumnA = Y.ColumnA
and Z.ColumnC <> Y.ColumnC
and Z.ColumnB > Y.ColumnB
you could also do this with a window function using lead and look ahead to the next record. but I don't know if your RDBMS supports window functions.
select t1.ColumnA, t1.ColumnB-t2.ColumnB diff from
tab t1, tab t2
where t1.columnA = t2.columnA and t1.ColumnC='True' and t2.ColumnC='False'
If your table name is myTable, I believe you can join the table with itself and on Column A and then select a difference in Column B when Column C is not equal to itself. So something like this
SELECT X.ColumnB - Y.ColumnB as Diff
FROM myTable as X
inner join
myTable as Y
on X.ColumnA=Y.ColumnA
WHERE X.ColumnC <> Y.ColumnC
You could use a self join
select a.column_A, a,column_B, b.column_B, a.column_B . b.column_B
from my_table a
inner join my_column b where a.column_a = b.column_a and a.column_c <> b_column_c
If you RDBMS supports window functions
;with cte as (
Select *
,Change = ColumnB-Lag(ColumnB,1) over (Partition By ColumnA Order By (Select null))
,TrueFalse = Lag(ColumnC,1) over (Partition By ColumnA Order By (Select null))
From #YourTable
)
Select ColumnA
,Change
From cte
Where Change<>0
and TrueFalse<>ColumnC
Returns
ColumnA Change
1234 2
5678 5
This one subtracts the "true" rows from the "false" rows, while preserving all true rows.
SELECT true.columna, true.columnb, COALESCE(false.columnb, 0) - true.columnb AS difference
FROM
(SELECT *
FROM t
WHERE columnc = "true") true
LEFT JOIN
(SELECT *
FROM t
WHERE columnc = "false) false
ON true.columna = false.columna
The coalesce clause will account for cases in which there is no false row. Without it you will end up trying to subtract from NULL.
If you're using Oracle, take a look at User Defined aggregate functions. If you define a function called diff(), then you can use select column_A, diff(column_B) from my_table group by column_A, but remember that the implementation of diff needs special care as different ordering will generate different results.

Select where column in not null array

I am trying to do :
SELECT *
FROM table
WHERE column IN (SELECT col FROM table2 WHERE col2 = value )
but I want to check if the second request doesn't return a null array.
How is that possible?
Thanks in advance
Simply add a NOT NULL check in the subquery to omit the null values returned.
SELECT * FROM table WHERE column IN
(SELECT col FROM table2 WHERE col2 = value AND col IS NOT NULL);