Rename single column in SELECT * in SQL, select all but a column - sql

here is what I'm trying to do- I have a table with lots of columns and want to create a view with one of the column reassigned based on certain combination of values in other columns, e.g.
Name, Age, Band, Alive ,,, <too many other fields)
And i want a query that will reassign one of the fields, e.g.
Select *, Age =
CASE When "Name" = 'BRYAN ADAMS' AND "Alive" = 1 THEN 18
ELSE "Age"
END
FROM Table
However, the schema that I now have is Name, Age, Band, Alive,,,,<too many>,, Age
I could use 'AS' in my select statment to make it
Name, Age, Band, Alive,,,,<too many>,, Age_Computed.
However, I want to reach the original schema of
Name, Age, Band, Alive.,,,, where Age is actually the computed age.
Is there a selective rename where I can do SELECT * and A_1 as A, B_1 as b? (and then A_1 completely disappears)
or a selective * where I can select all but certain columns? (which would also solve the question asked in the previous statement)
I know the hacky way where I enumerate all columns and create an appropriate query, but I'm still hopeful there is a 'simpler' way to do this.

Sorry, no, there is not a way to replace an existing column name using a SELECT * construct as you desire.
It is always better to define columns explicitly, especially for views, and never use SELECT *. Just use the table's DDL as a model when you create the view. That way you can alter any column definition you want (as in your question) and eliminate columns inappropriate for the view. We use this technique to mask or eliminate columns containing sensitive data like social security numbers and passwords. The link provided by marc_s in the comments is a good read.

Google BigQuery supports SELECT * REPLACE:
A SELECT * REPLACE statement specifies one or more expression AS identifier clauses. Each identifier must match a column name from the SELECT * statement.
In the output column list, the column that matches the identifier in a REPLACE clause is replaced by the expression in that REPLACE clause.
A SELECT * REPLACE statement does not change the names or order of columns. However, it can change the value and the value type.
Select *, Age = CASE When "Name" = 'BRYAN ADAMS' AND "Alive" = 1 THEN 18
ELSE "Age"
END
FROM tab
=>
SELECT * REPLACE(CASE WHEN Name = 'BRYAN ADAMS' AND Alive = 1 THEN 18
ELSE Age END AS Age)
FROM Tab

Actually, there is a way to do this in MySQL. You need to use a hack to select all but one column as posted here, then add it separately in the AS statement.
Here is an example:
-- Set-up some example data
DROP TABLE IF EXISTS test;
CREATE TABLE `test` (`ID` int(2), `date` datetime, `val0` varchar(1), val1 INT(1), val2 INT(4), PRIMARY KEY(ID, `date`));
INSERT INTO `test` (`ID`, `date`, `val0`, `val1`, `val2`) VALUES
(1, '2016-03-07 12:20:00', 'a', 1, 1001),
(1, '2016-04-02 12:20:00', 'b', 2, 1004),
(1, '2016-03-01 10:09:00', 'c', 3, 1009),
(1, '2015-04-12 10:09:00', 'd', 4, 1016),
(1, '2016-03-03 12:20:00', 'e', 5, 1025);
-- Select all columns, renaming 'val0' as 'yabadabadoo':
SET #s = CONCAT('SELECT ', (SELECT REPLACE(GROUP_CONCAT(COLUMN_NAME), 'val0,', '')
FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'test' AND TABLE_SCHEMA =
'<database_name>'), ', val0 AS `yabadabadoo` FROM test');
PREPARE stmt1 FROM #s;
EXECUTE stmt1;

Related

Is there any way to output the result of a column of each row to show a different value in OracleDB using PL/SQL?

I have a Select Statement that has a column which is a code value. For e.g. instead of Java its JV, and instead of Python its PY. However, instead of outputting the coded value, I would like to display them as Java or Python i.e. their full description. Is there a way to do this with PL/SQL?
Any help would be greatly appreciated, thanks!
you can use case expression
select
case
when myColumn = 'JV' then 'Java'
when myColumn = 'PY' then 'Python'
end as myColumn
from yourTable
In oracle you can use decode as well.
decode(col, 'JV', 'Java',
'PY', 'Python'
'No Match'
)
Given that you are using Oracle, I would recommend using the DECODE function:
SELECT
col,
DECODE(col, 'JV', 'Java',
'PY', 'Python',
'Not found') AS col_out
FROM yourTable;
You can use either the "DECODE" function, or a "CASE" construct, as follows:
select DECODE(my_column,
'JV','Java',
'PY','Python',
'no_match_found') my_column_alias
from my_table;
select
case my_column
when 'JV' then 'Java'
when 'PY' then 'Python'
else 'no_match_found'
end my_column_alias
from my_table;
While there are several ways of hard coding the for the sample data given none are the proper method for more than a very limited set. The proper method is to create a lookup table. In this case contains the code and corresponding name. Yes, it is quite overkill for 2 languages, but how about the TIOBE Index or the 700 listed in Wikipedia, or the estimated approximately 9000 claimed in the HOPL list. See here and additional links more.
Moreover it is a standard technique to OP underlying question: Is there a way to give detail about a given code value.
It is easily extended (just add row to a table) and applicable across virtually all domains (abet with slight modifications).
-- create language lookup
create table language_lookup(
code varchar2(8)
, name varchar2(200)
, description varchar2(4000)
, constraint language_lookup_pk
primary key (code)
);
insert into language_lookup(code, name)
select 'JV','Java' from dual union all
select 'PY','Python' from dual ;
-- your table
create table your_table ( id integer
, lang_code varchar2(8)
--...
, constraint your_table_pk
primary key (id)
, constraint your_table_2_language_lookup_fk
foreign key (lang_code)
references language_lookup(code)
) ;
insert into your_table (id, lang_code)
select 1,'JV' from dual union all
select 2,'PY' from dual;
select yt.lang_code, ll.name
from your_table yt
join language_lookup ll
on ll.code = yt.lang_code
where yt.lang_code in ('JV','PY')
;
-- now modify to include plsql
insert into language_lookup(code, name)
values ( 'PLSQL', 'Oracle''s Programming Language extension for SQL');
insert into your_table (id,lang_code)
values (3,'PLSQL');
select yt.lang_code, ll.name
from your_table yt
join language_lookup ll
on ll.code = yt.lang_code
;
Try that with your hard coded values. Then add 30 - 40 more ...

Is there a SQL SELECT to rename one column preserving column order? [duplicate]

here is what I'm trying to do- I have a table with lots of columns and want to create a view with one of the column reassigned based on certain combination of values in other columns, e.g.
Name, Age, Band, Alive ,,, <too many other fields)
And i want a query that will reassign one of the fields, e.g.
Select *, Age =
CASE When "Name" = 'BRYAN ADAMS' AND "Alive" = 1 THEN 18
ELSE "Age"
END
FROM Table
However, the schema that I now have is Name, Age, Band, Alive,,,,<too many>,, Age
I could use 'AS' in my select statment to make it
Name, Age, Band, Alive,,,,<too many>,, Age_Computed.
However, I want to reach the original schema of
Name, Age, Band, Alive.,,,, where Age is actually the computed age.
Is there a selective rename where I can do SELECT * and A_1 as A, B_1 as b? (and then A_1 completely disappears)
or a selective * where I can select all but certain columns? (which would also solve the question asked in the previous statement)
I know the hacky way where I enumerate all columns and create an appropriate query, but I'm still hopeful there is a 'simpler' way to do this.
Sorry, no, there is not a way to replace an existing column name using a SELECT * construct as you desire.
It is always better to define columns explicitly, especially for views, and never use SELECT *. Just use the table's DDL as a model when you create the view. That way you can alter any column definition you want (as in your question) and eliminate columns inappropriate for the view. We use this technique to mask or eliminate columns containing sensitive data like social security numbers and passwords. The link provided by marc_s in the comments is a good read.
Google BigQuery supports SELECT * REPLACE:
A SELECT * REPLACE statement specifies one or more expression AS identifier clauses. Each identifier must match a column name from the SELECT * statement.
In the output column list, the column that matches the identifier in a REPLACE clause is replaced by the expression in that REPLACE clause.
A SELECT * REPLACE statement does not change the names or order of columns. However, it can change the value and the value type.
Select *, Age = CASE When "Name" = 'BRYAN ADAMS' AND "Alive" = 1 THEN 18
ELSE "Age"
END
FROM tab
=>
SELECT * REPLACE(CASE WHEN Name = 'BRYAN ADAMS' AND Alive = 1 THEN 18
ELSE Age END AS Age)
FROM Tab
Actually, there is a way to do this in MySQL. You need to use a hack to select all but one column as posted here, then add it separately in the AS statement.
Here is an example:
-- Set-up some example data
DROP TABLE IF EXISTS test;
CREATE TABLE `test` (`ID` int(2), `date` datetime, `val0` varchar(1), val1 INT(1), val2 INT(4), PRIMARY KEY(ID, `date`));
INSERT INTO `test` (`ID`, `date`, `val0`, `val1`, `val2`) VALUES
(1, '2016-03-07 12:20:00', 'a', 1, 1001),
(1, '2016-04-02 12:20:00', 'b', 2, 1004),
(1, '2016-03-01 10:09:00', 'c', 3, 1009),
(1, '2015-04-12 10:09:00', 'd', 4, 1016),
(1, '2016-03-03 12:20:00', 'e', 5, 1025);
-- Select all columns, renaming 'val0' as 'yabadabadoo':
SET #s = CONCAT('SELECT ', (SELECT REPLACE(GROUP_CONCAT(COLUMN_NAME), 'val0,', '')
FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'test' AND TABLE_SCHEMA =
'<database_name>'), ', val0 AS `yabadabadoo` FROM test');
PREPARE stmt1 FROM #s;
EXECUTE stmt1;

Concatenate return type for a crosstab() query from another query

I can't post my original query here, it's too complex. So I am explaining my problem with a sample query:
Working pivot query:
Select pivot.* from public.crosstab($$ select 'na' as na, 1 as analysis,100 as value
union all select 'ba' as na, 2 as analysis,100 as value $$,
$$ VALUES ('1'), ('2')$$
) as pivot (na text, "1" integer,"2" integer)
But I would like to use it like this:
Select pivot.* from public.crosstab($$ select 'na' as na, 1 as analysis,100 as value
union all select 'ba' as na, 2 as analysis,100 as value $$,
$$ VALUES ('1'), ('2')$$
) as pivot select '(na text,"1" integer,"2" integer)'
I want to add the return type from a query (bold emphasis). How to do that?
Clear test case
First I formated and clarified your example:
SELECT * FROM public.crosstab(
$$VALUES ('na', 1, 100) -- VALUES expression does the same, shorter
, ('ba', 2, 300)$$ -- no column names needed (ignored anyway)
,$$VALUES ('1'), ('2')$$
) AS pivot (na text, co11 int, col2 int) -- sane column names
Input table:
col1 key val
---------------
na 1 100
ba 2 300
Output table
na co11 col2
--------------------
na 100 <NULL>
ba <NULL> 300
You can pick output column names freely, no need to stick to unwieldy names like "1", "2". Only the data types have to match.
Dynamic return type
You cannot provide the column definition list from a query. We have had many similar requests here on SO. They all clash with the nature of SQL, which does not accept a return type "after the fact". Must be declared with the query, at least at the time of executing it.
You would have to build the crosstab() query with the output of the SELECT query you want to add in your 2nd example. Two round trips to the server.
But we can read a well know type from the system catalogs - that's what SELECT * FROM tbl does after all. I have tried hard and implemented what I found in this related answer:
Dynamic alternative to pivot with CASE and GROUP BY
My function crosstab_n() is probably your best shot. Read the linked answer!
It's a wrapper around crosstab() that takes the query string (just like crosstab()) and an additional polymorphic parameter that provides the return type. We still cannot pass the return type on the fly. The only acceptable way for SQL is to read it from the system catalog. So we install a composite type "on the fly" by way of creating a temporary table:
CREATE TEMP TABLE my_pivot (na text, col1 int, col2 int);
SELECT * FROM crosstab_n(
$$VALUES ('na', 1, 100), ('ba', 2, 100)$$
,NULL::my_pivot
);
Result as above. VoilĂ !
If you want the temp table to last for the transaction only, add ON COMMIT DROP to it. Both statements must be executed in one transaction then. Details:
Select from a table variable

Oracle INSERT INTO with select and values

I'm trying to insert some values into a table from a select statement and some hardcoded values, but I'm not sure what the syntax would be. When I try I get an error saying there are not enough values so I know it's not reading my select statement correctly. Any help is appreciated.
insert into INSERT_STG
values(
(select code,
acct,
to_char(sysdate, 'mmddyy'),
amt
from schema.table),
'Partners',
'city',
'st',
'Y',
null,
);
insert into INSERT_STG
(select code,
acct,
to_char(sysdate, 'mmddyy'),
amt ,
'Partners',
'city',
'st',
'Y',
null
from schema.table);
Problems:
You had extra comma after null
You can't combine hardcoded values and the select like you did. The hard coded values have to be generated as part of the select.
This should work assuming: INSERT_STG has 9 columns of the datatypes in schema.table in the order of the select and string and support null on last column.
Get rid of the "values" line and ensure you're inserting the same count of values as the table INSERT_STG has. Otherwise, explicitly specify columns of target table to insert.

How to select a column without its name in sql server?

how to
select name,family from student where name="X"
without its column name.
for example :
select "column1","column2" from student where "column1"="x"
or for example
select "1","2" from student where "1"="x"
"1" is column1
"2" is column2
i dont want to say columns name. i want to say just its number or other....
idont tired from select *. but it just for that i dont know the columns name but i know where they are. my columns name are change every i want to read the file but its data are same, and the data are in the same columns in each file.
Although you can not use field positions specifiers in the SELECT statement, the SQL standard includes the INFORMATION_SCHEMA where the dictionary of your tables is defined. This includes the COLUMNS view where all the fields of all tables are defined. And in this view, there is a field called ORDINAL_POSITION which you can use to assist in this problem.
If you query
SELECT ORDINAL_POSITION, COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'TABLE'
ORDER BY ORDINAL_POSITION
then you can obtain the column names for the ordinal positions you want. From there you can prepare a SQL statement.
You could use temp table as:
DECLARE #TB TABLE(Column1 NVARCHAR(50),...)
INSERT #TB
SELECT * FROM student
Then use it:
SELECT Column1 FROM #TB WHERE Column1='aa'
If it's a string you can do this :
Select Column1 + '' From Table
If it's a number you can do this :
Select Column1 + 0 From Table
If it's a datetime you can do this :
Select dateadd(d, 0, Column1) From Table
And similarly for other data types..
No, you can not use the ordinal (numeric) position in the SELECT clause. Only in Order by you can.
however you can make your own column alias...
Select Column1 as [1] From Table
You can use alias:
SELECT name AS [1], family AS [2] FROM student WHERE name="X"
It's just not possible. Unfortunately, they didn't think about table-valued functions, for which information_schema is not available, so good luck with that.