Create column with values from multiple columns in SQL - sql

I want to add a column to a table that includes value from one of two columns, depending on which row contains the value.
For instance,
SELECT
concat("Selecting Col1 or 2", cast("Col1" OR "Col2" as string)) AS relevantinfo,
FROM table
I do not know much SQL and I know this query does not work. Is this even possible to do?
Col1 Col2
1
4
3
4
5
FINAL RESULT
Col1 Col2 relevantinfo
1 1
4 4
3 3
4 4
5 5

You can use the COALESCE function, which will return the first non-null value in the list.
SELECT col1, col2, COALESCE(col1, col2) AS col3
FROM t1;
Working example: http://sqlfiddle.com/#!9/05a83/1

I wouldn't alter the table structure to add a redundant information that can be retrieved with a simple query.
I would rather use that kind of query with IFNULL/ISNULL(ColumnName, 'Value to use if the col is null'):
--This will work only if there can't be a value in both column at the same time
--Mysql
SELECT CONCAT(IFNULL(Col1,''),IFNULL(Col2,'')) as relevantinfo FROM Table
--Sql Server
SELECT CONCAT(ISNULL(Col1,''),ISNULL(Col2,'')) as relevantinfo FROM Table

Related

How to duplicate records, modify and add them to same table

I got some question and hopefully you can help me out. :)
What I have is a table like this:
ID Col1 Col2 ReverseID
1 Number 1 Number A
2 Number 2 Number B
3 Number 3 Number C
What I want to achieve is:
Create duplicate of every record with switched columns and add them to original table
Add the ID of the duplicate to ReverseID column of original record and vice-versa
So the new table should look like:
ID Col1 Col2 ReverseID
1 Number 1 Number A 4
2 Number 2 Number B 5
3 Number 3 Number C 6
4 Number A Number 1 1
5 Number B Number 2 2
6 Number C Number 3 3
What I've done so far was working with temporary table:
SELECT * INTO #tbl
FROM myTable
UPDATE #tbl
SET Col1 = Col2,
Col2 = Col1,
ReverseID = ID
INSERT INTO DUPLICATEtable(
Col1,
Col2,
ReverseID
)
SELECT Col1,
Col2,
ReverseID
FROM #tbl
In this example code I used a secondary table just for making sure I do not compromise the original data records.
I think I could skip the SET-part and change the columns in the last SELECT statement to achieve the same, but I am not sure.
Anyway - with this I am ending up at:
ID Col1 Col2 ReverseID
1 Number 1 Number A
2 Number 2 Number B
3 Number 3 Number C
4 Number A Number 1 1
5 Number B Number 2 2
6 Number C Number 3 3
So the question remains: How do I get the ReverseIDs correctly added to original records?
As my SQL knowledge is pretty low I am almost sure, this is not the simplest way of doing things, so I hope you guys & girls can enlighten me and lead me to a more elegant solution.
Thank you in advance!
br
mrt
Edit:
I try to illustrate my initial problem, so this posting gets long. ;)
.
First of all: My frontend does not allow any SQL statements, I have to focus on classes, attributes, relations.
First root cause:
Instances of a class B (B1, B2, B3, ...) are linked together in class Relation, these are many-to-many relations of same class. My frontend does not allow join tables, so that's a workaround.
Stating a user adds a relation with B1 as first side (I just called it 'left') and B2 as second side (right):
Navigating from B1, there will be two relations showing up (FK_Left, FK_Right), but only one of them will contain a value (let's say FK_Left).
Navigating from B2, the value will be only listed in the other relation (FK_Right).
So from the users side, there are always two relations displayed, but it depends on how the record was entered, if one can find the data behind relation_left or relation_right.
That's no practicable usability.
If I had all records with vice-versa partners, I can just hide one of the relations and the user sees all information behind one relation, regardless how it was entered.
Second root cause:
The frontend provides some matrix view, which gets the relation class as input and displays left partners in columns and right partners in rows.
Let's say I want to see all instances of A in columns and their partners in rows, this is only possible, if all relations regarding the instances of A are entered the same way, e.g. all A-instances as left partner.
The matrix view shall be freely filterable regarding rows and columns, so if I had duplicate relations, I can filter on any of the partners in rows and columns.
sorry for the long text, I hope that made my situation a bit clearer.
I would suggest just using a view instead of trying to create and maintain two copies of the same data. Then you just select from the view instead of the base table.
create view MyReversedDataView as
select ID
, Col1
, Col2
from MyTable
UNION ALL
select ID
, Col2
, Col1
from MyTable
The trick to this kind of thing is to start with a SELECT that gets the data you need. In this case you need a resultset with Col1, Col2, reverseid.
SELECT Col2 Col1, Col1 Col1, ID reverseid
INTO #tmp FROM myTable;
Convince yourself it's correct -- swapped column values etc.
Then do this:
INSERT INTO myTable (Col1, col2, reverseid)
SELECT Col1, Col2, reverseid FROM #tmp;
If you're doing this from a GUI like ssms, don't forget to DROP TABLE #tmp;
BUT, you can get the same result with a pure query, without duplicating rows. Why do it this way?
You save the wasted space for the reversed rows.
You always get the reversed rows up to the last second, even if you forget to run the process for reversing and inserting them into the table.
There's no consistency problem if you insert or delete rows from the table.
Here's how you might do this.
SELECT Col1, Col2, null reverseid FROM myTable
UNION ALL
SELECT Col2 Col1, Col1 Col2, ID reverseid FROM myTable;
You can even make it into a view and use it as if it were a table going forward.
CREATE VIEW myTableWithReversals AS
SELECT Col1, Col2, null reverseid FROM myTable
UNION ALL
SELECT Col2 Col1, Col1 Col2, ID reverseid FROM myTable;
Then you can say SELECT * FROM myTableWithReversals WHERE Col1 = 'value' etc.
Let me assume that the id column is auto-incremented. Then, you can do this in two steps:
insert into myTable (Col1, Col2, reverseid)
select col2, col1, id
from myTable t
order by id; -- ensures that they go in in the right order
This inserts the new ids with the right reverseid. Now we have to update the previous values:
update t
set reverseid = tr.id
from myTable t join
myTable tr
on tr.reverseid = t.id;
Note that no temporary tables are needed.

SQL - get only colums from a table where not all values are nulls

SQL question:
How do I get all column values from columns where not all values are null?
Table A
COL1 COL2 COL3 COL4 COL5
---------------------------------------
abc 1 NULL NULL NULL
def 2 NULL testA NULL
NULL 3 NULL testB NULL
jkl 4 NULL NULL NULL
I want to get
COL1 COL2 COL4
-----------------------
abc 1 NULL
def 2 testA
NULL 3 testB
jkl 4 NULL
Is there a sql or plsql solution achieve this this?
To avoid answers that are irrelevant: assume I have a million rows.
I want the result to be a view or a result table.
Not a written output.
I found a similar question, but it does not satisfy my need:
How to select columns from a table which have non null values?
The column names can be quickly grabbed through this query
select column_name
from all_tab_columns
where lower(table_name)='tableA' and num_distinct > 0;
I understand I could create a script with a cursor and then loop through it, adding the result to a new table or view.
This is not what I need. I wondered if this could be done using a single query, using pivot/unpivot or something else.
What you are asking for is not possible in plain SQL, unless you know ahead of time which columns only have NULL everywhere. (It seems that you don't want to assume that you know that.)
Which columns are included in the output - how many columns, their names, and in what order they appear - must be hard-coded in the SELECT clause, it can't be determined at runtime. On the other hand, you will only know which columns are all-NULL only after reading the data (meaning, at runtime) - or else you must have that information from an external source.
The only way to do what you seem to want to do is with dynamic SQL. That is an advanced topic, and a technique generally considered a poor business practice.
WHY do you not want to show columns with all-NULL values? Are you sure that requirement is meaningful?
try these steps, it may help:
Create table temp as (Select * from TableA)
Declare NbrRows Number(10);
plsql_block VARCHAR2(1000);
CountNullRows Number (10)
Select count(*) as nbr
into NbrRows
from TableA
Select count(COL1) as nbr
into CountNullRows
from TableA where COL1 is null
if (NbrRows = CountNullRows) then
Alter table Temp drop column COL1
endif
Select count(COL2) as nbr
into CountNullRows
from TableA where COL2 is null
if (NbrRows = CountNullRows) then
Alter table Temp drop column COL2
endif
Select count(COL3) as nbr
into CountNullRows
from TableA where COL3 is null
if (NbrRows = CountNullRows) then
Alter table Temp drop column COL3
endif
...etc...
Do the same thing for all your columns
You have the desired result in the Tem table.

Reject a row based on 2 column values

Below is the output of a simple join query. All the 3 columns are from different tables.
Col1 Col2 Col3
Manual Y-Yes Include
MC Y-Yes Include
Manual Y-Yes Exclude
Manual Y-Yes Exclude
I need to get the rows with 'Include' only if there is no 'Exclude' for the same Col1 value.
If there is no 'Exclude' for the Col1 value, then its fine to display 'Include'.
So the query should not display the first row according to the requirement since the Col1 value 'Manual' has 'Exclude'.
Your sql query should look a lot like what your question would be in English:
You want all the rows where there is no row for the same col1 value that has 'Exclude' in the col3 value, right?
I cannot give exact sql since you do not provide table or column names, but if all three columns were in the same table, it would look like this:
Select * from mytable
where not exists
(select * from mytable
where col1 = t.col1
and col3 = 'Exclude')

oracle insert after updating x columns data of the selected data

I need to achieve a functionality in my project:
I have to select 10 rows from a table having 5 columns and then insert the data in same table after updating 2 columns of the data retrieved (from the select query) ...what query will do for achieving the same functionality.
example :(10 rows)
data in column1 is 'zz','zz','zz','zz','zz','zz','zz','zz','zz','zz'.
data in column2 is 'ClassA','ClassB','ClassC','ClassD','ClassE','ClassA','ClassB','ClassC','ClassD','ClassE'
INSERT INTO tableT (SELECT * FROM tableT (update column1='yy',column2=append '_tt' on the existing data in the rows column))
after firing query, we have 20 records, 10 old and 10 new.
10 new records data will be
column1 is 'yy','yy','yy','yy','yy','yy','yy','yy','yy','yy'
data in column2 is 'ClassA_tt','ClassB_tt','ClassC_tt','ClassD_tt','ClassE_tt','ClassA_tt','ClassB_tt','ClassC_tt','ClassD_tt','ClassE_tt'
and the data of other remaining 3 columns will be same
please guide me in framing the query
It depends on the size of your query and on the way you want data to be updated. But for your example you could use
insert into table (column1,column2)
select decode(column2,'1','yy','2','zz',null) col1, col2 from table;
EDIT:
After you changed your question I dont understand what you want to do at all. Please explain this:
data in column2 is abc,bcd,dce,xyz,etc
because I dont get the pattern.
EDIT 2:
OK. Here we go:
INSERT INTO <table_name> (col1,col2,col3,col4,col5)
SELECT col1,col2,col3,col4,col5
FROM (
select 'yy' as col1 , (col2 || '_tt') as col2,col3,col4,col5, rownum r_num
from <table_name>
) where r_num <= 10;
You didnt specify which 10 rows you want. This will select and change firs 10 rows returned by inner select query.

how to get the rows from two table instead of one when their is sure that they exist in one

i have two table in mysql database. the row have primary key ID 5 is sure that exist in one or if not then exist in 2
how i can retrive them by making a command in MySQL
Assuming that your tables have the same structure, you could do this using UNION ALL:
SELECT col1, col2, col3 FROM table1 WHERE ID = 5
UNION ALL
SELECT col1, col2, col3 FROM table2 WHERE ID = 5
LIMIT 1
You could also consider changing your schema so that you only have one table with a field to store whether it is type one or type two.