Change only single column values when we use * in sql - sql

Is there a way to change only single column values as updated in selection of oracle sql.
SELECT ORDD.id||'sdaf' as id,ORDD.*
FROM RDT_ORDER ORDM,RDT_ORDERDETAIL ORDD;
Here in RDT_ORDERDETAIL am having around Hundered columns but only single coulmn I need as updated.
I don't want to select all Hundred columns by writing all columns in select query as below
SELECT ORDD.id||'sdaf' as id,ORDD.col1,ORDD.col2,ORDD.col3,ORDD.col4
FROM RDT_ORDER ORDM,RDT_ORDERDETAIL ORDD;
Please note I have removed where clause,I need to get single updated column values other columns as it is.But I shouldn't write all coulmns in Select.
Existing DB Records :
ID NAME COL3 COL4
1 name1 .. ..
2 name2 .. ..
3 name3 .. ..
Now Result :
ID ID NAME COL3 COL4
1_'sdaf' 1 name1 .. ..
2_'sdaf' 2 name2 .. ..
3_'sdaf' 3 name3 .. ..
Expected Result :
ID NAME COL3 COL4
1_'sdaf' name1 .. ..
2_'sdaf' name2 .. ..
3_'sdaf' name3 .. ..

If you want to select all but one rows then the answer is No - you either get all fields (*) OR specify the fields you want. This is how Oracle works.
If you still persists, then there might be some work around like Dynamic SQL using query generator or data cartridge
You can refer here for similar question.
If you want to have a string manipulation and all columns you can do using alias.
SELECT COL1||'_asd_', T.*
FROM MYTABLE T;
Your idea of getting all columns from a table with a manipulation on one or more columns without writers cramp is not possible directly. You may try dynamic SQL but I will not suggest that for anything because of low maintainability and its a head ache on a long run.

I don't think you can exclude a single column by quering with select * from.... May be a VIEW can help you on this.
CREATE OR REPLACE VIEW <view_name> AS
SELECT ordd.id||'sdaf' AS id, ordd.col1, ordd.col2, ordd.col3, ordd.col4
FROM rdt_order ordm,
rdt_orderdetail ordd
WHERE .....;

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.

Create column with values from multiple columns in 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

In SQL server, how to fetch column names from a source except target query for which data does not match

I have to find out the name of columns which have different data in a source except target query.
Currently when I am executing a Source except Target query, Even if there is only one column value is different, it's returning entire row. My requirement is to find out names of such columns which have data difference and put them into a separate table.
For example if I have a table as below:
Select * from A;
Col1 Col2 Col3 Col4
1 A India Delhi
2 A US Newyork
when I Query:
Select * from A where Col1=1
except
select * from A where Col1=2
It will display:
Col1 Col2 Col3 Col4
1 A India Delhi
However I need to populate Col1 (Key field) value and Col3,Col4 names(Column names, which were not found to be same at the time of except query execution) into a new table.
I think your approach has a conceptual bug.
Assuming your tables are
Col1 Col2
---- ----
A A
B B
C C
Col1 Col2
---- ----
A A
B C
C B
If you use "SELECT Expect", you're happy to find that the first tuple is unchanged. After that, the problem is that you have no way to mach the remaining rows. Does B-B matches B-C or C-B or C-C was update or B-B and C-C have been deleted and the other are new rows?
You MUST rely on a key of any kind. Assuming you do it, the rest is conventional boring SQL.

Insert records into a table based on value of a record in another table

I am trying to create a quotation system using Microsoft Access 2013.
Currently, my main issue to trying to write a query that selects all records from a table (itemquote) that have a certain quoteID matching the quoteID coming from another table (currentquote), and then inserts the results into a new table (quoteditems).
Here is a basic example of the tables:
ItemQuote
UniqueID ItemID QuoteID BuyPrice SellPrice
1 1 1 10.00 11.00
2 8 2 07.00 14.00
3 4 5 01.12 03.00
CurrentQuote
CurrentQuoteID
1
My current attempt at writing the query looks like this:
INSERT INTO tblQuotedItems
SELECT *
FROM tblQuoteAsBuiltAndLabelling
INNER JOIN tblCurrentQuote
ON tblQuoteAsBuiltAndLabelling.QuoteID = tblCurrentQuote.CurrentQuoteID;
The resulting error message is "The INSERT INTO statement contains the following unknown field name: 'CurrentQuoteID'. Make sure you have typed the name correctly, and try the operation again." (Error 3127)
What should I do to my query to make it achieve the desired result? Thanks in advance.
The problem may be because your tblQuotedItems does not have the same number of column what your Select Query Returns.
So to resolve this, You can specified individual columns in INSERT Statement, and that will solve your problem.
You can not specify column names in the insert if the columns in the select are in the same order as in the table definition. Possibly, the columns in the current quote might be the same. If so, this might work:
INSERT INTO tblQuotedItems
SELECT tblCurrentQuote.*
FROM tblQuoteAsBuiltAndLabelling INNER JOIN
tblCurrentQuote
ON tblQuoteAsBuiltAndLabelling.QuoteID = tblCurrentQuote.CurrentQuoteID;
However, I strongly recommend that you include column names explicitly when you do inserts:
INSERT INTO tblQuotedItems(col1, col2, . . .)
SELECT col1, col2, . . .
FROM tblQuoteAsBuiltAndLabelling INNER JOIN
tblCurrentQuote
ON tblQuoteAsBuiltAndLabelling.QuoteID = tblCurrentQuote.CurrentQuoteID;

oracle transpose based on column values

I know transpose (or pivot) w/ sql is a common ask, but I haven't been able to get to exactly what I'm trying to do on stack/google.
In short, I want case when/then without hardcoding all possible values of a column because these values may be numerous and/or change over time. For example,
id col val
1 a 65
1 b 34
1 c 25
2 a 67
2 c 22
...
the goal is to wind up with a single row for each distinct id, with columns for each distinct col
Easy enough when the values of col are static and small, but when there are dozens of such values hardcoding every possible clause in a case statement seems arduous.
in psuedo code, what i want to do is
select
for each attr in (select distinct col from table)
sum(case when col = attr then val end) as transposed_attr,
end for
from table
group by id
But i'm inexperienced with PL/SQL, so I don't know how to achieve this in oracle.
Advice?
What version of Oracle? 11g introduces the pivot command...
Infact, just look here for both using PIVOT command and not:
http://orafaq.com/wiki/PIVOT