How can I exclude GUIDs from a select distinct without listing all other columns in a table? - sql

So let's say 'table' has two columns that act as a GUID - the ID column and msrepl_tran_version. Our original programmer did not know that our replication created this column and included it in a comparison, which has resulted in almost 20,000 records being put into this table, of which only 1,588 are ACTUALLY unique, and it's causing long load times.
I'm looking for a way to exclude the ID and replication columns from a select distinct, without having to then list every single column in the table, since I'm going to have to select from the record set multiple times to fix this (there are other tables affected and the query is going to be ridiculous) I don't want to have to deal with my code being messy if I can help it.
Is there a way to accomplish this without listing all of the other columns?
Select distinct {* except ID, msrepl_tran_version} from table
Other than (where COL_1 is ID and COL_N is the replication GUID)
Select distinct COL_2, ..., COL_N-1, COL_N+1, ... from table

After more searching, I found the answer:
SELECT * INTO #temp FROM table
ALTER TABLE #temp DROP COLUMN id
ALTER TABLE #temp DROP COLUMN msrepl_tran_version
SELECT DISTINCT * FROM #temp
This works for what I need. Thanks for the answers guys!

Absolutely, 100% not possible, there is no subtract columns instruction.

It can't be done in the spirit of the OP's initial question. However, it can be done with dynamic sql:
--Dynamically build list of column names.
DECLARE #ColNames NVARCHAR(MAX) = ''
SELECT #ColNames = #ColNames + '[' + c.COLUMN_NAME + '],'
FROM INFORMATION_SCHEMA.COLUMNS c
WHERE c.TABLE_SCHEMA = 'dbo'
AND c.TABLE_NAME = 'YourTable'
--Exclude these.
AND c.COLUMN_NAME NOT IN ('ID', 'msrepl_tran_version')
--Keep original column order for appearance, convenience.
ORDER BY c.ORDINAL_POSITION
--Remove trailing comma.
SET #ColNames = LEFT(#ColNames, LEN(#ColNames) - 1)
--Verify query
PRINT ('SELECT DISTINCT ' + #ColNames + ' FROM [dbo].[YourTable]')
--Uncomment when ready to proceed.
--EXEC ('SELECT DISTINCT ' + #ColNames + ' FROM [dbo].[YourTable]')
One additional note: since you need to select from the record set multiple times and potentially join to other tables, you can use the above to create a view on the table. This should make your code fairly clean.

Related

SQL joining huge tables by excluding just one column in select statement [duplicate]

I'm trying to use a select statement to get all of the columns from a certain MySQL table except one. Is there a simple way to do this?
EDIT: There are 53 columns in this table (NOT MY DESIGN)
Actually there is a way, you need to have permissions of course for doing this ...
SET #sql = CONCAT('SELECT ', (SELECT REPLACE(GROUP_CONCAT(COLUMN_NAME), '<columns_to_omit>,', '') FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '<table>' AND TABLE_SCHEMA = '<database>'), ' FROM <table>');
PREPARE stmt1 FROM #sql;
EXECUTE stmt1;
Replacing <table>, <database> and <columns_to_omit>
(Do not try this on a big table, the result might be... surprising !)
TEMPORARY TABLE
DROP TABLE IF EXISTS temp_tb;
CREATE TEMPORARY TABLE ENGINE=MEMORY temp_tb SELECT * FROM orig_tb;
ALTER TABLE temp_tb DROP col_a, DROP col_f,DROP col_z; #// MySQL
SELECT * FROM temp_tb;
DROP syntax may vary for databases #Denis Rozhnev
Would a View work better in this case?
CREATE VIEW vwTable
as
SELECT
col1
, col2
, col3
, col..
, col53
FROM table
You can do:
SELECT column1, column2, column4 FROM table WHERE whatever
without getting column3, though perhaps you were looking for a more general solution?
If you are looking to exclude the value of a field, e.g. for security concerns / sensitive info, you can retrieve that column as null.
e.g.
SELECT *, NULL AS salary FROM users
To the best of my knowledge, there isn't. You can do something like:
SELECT col1, col2, col3, col4 FROM tbl
and manually choose the columns you want. However, if you want a lot of columns, then you might just want to do a:
SELECT * FROM tbl
and just ignore what you don't want.
In your particular case, I would suggest:
SELECT * FROM tbl
unless you only want a few columns. If you only want four columns, then:
SELECT col3, col6, col45, col 52 FROM tbl
would be fine, but if you want 50 columns, then any code that makes the query would become (too?) difficult to read.
While trying the solutions by #Mahomedalid and #Junaid I found a problem. So thought of sharing it. If the column name is having spaces or hyphens like check-in then the query will fail. The simple workaround is to use backtick around column names. The modified query is below
SET #SQL = CONCAT('SELECT ', (SELECT GROUP_CONCAT(CONCAT("`", COLUMN_NAME, "`")) FROM
INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'users' AND COLUMN_NAME NOT IN ('id')), ' FROM users');
PREPARE stmt1 FROM #SQL;
EXECUTE stmt1;
If the column that you didn't want to select had a massive amount of data in it, and you didn't want to include it due to speed issues and you select the other columns often, I would suggest that you create a new table with the one field that you don't usually select with a key to the original table and remove the field from the original table. Join the tables when that extra field is actually required.
You could use DESCRIBE my_table and use the results of that to generate the SELECT statement dynamically.
My main problem is the many columns I get when joining tables. While this is not the answer to your question (how to select all but certain columns from one table), I think it is worth mentioning that you can specify table. to get all columns from a particular table, instead of just specifying .
Here is an example of how this could be very useful:
select users.*, phone.meta_value as phone, zipcode.meta_value as zipcode
from users
left join user_meta as phone
on ( (users.user_id = phone.user_id) AND (phone.meta_key = 'phone') )
left join user_meta as zipcode
on ( (users.user_id = zipcode.user_id) AND (zipcode.meta_key = 'zipcode') )
The result is all the columns from the users table, and two additional columns which were joined from the meta table.
I liked the answer from #Mahomedalid besides this fact informed in comment from #Bill Karwin. The possible problem raised by #Jan Koritak is true I faced that but I have found a trick for that and just want to share it here for anyone facing the issue.
we can replace the REPLACE function with where clause in the sub-query of Prepared statement like this:
Using my table and column name
SET #SQL = CONCAT('SELECT ', (SELECT GROUP_CONCAT(COLUMN_NAME) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'users' AND COLUMN_NAME NOT IN ('id')), ' FROM users');
PREPARE stmt1 FROM #SQL;
EXECUTE stmt1;
So, this is going to exclude only the field id but not company_id
Yes, though it can be high I/O depending on the table here is a workaround I found for it.
SELECT *
INTO #temp
FROM table
ALTER TABLE #temp DROP COlUMN column_name
SELECT *
FROM #temp
It is good practice to specify the columns that you are querying even if you query all the columns.
So I would suggest you write the name of each column in the statement (excluding the one you don't want).
SELECT
col1
, col2
, col3
, col..
, col53
FROM table
I agree with the "simple" solution of listing all the columns, but this can be burdensome, and typos can cause lots of wasted time. I use a function "getTableColumns" to retrieve the names of my columns suitable for pasting into a query. Then all I need to do is to delete those I don't want.
CREATE FUNCTION `getTableColumns`(tablename varchar(100))
RETURNS varchar(5000) CHARSET latin1
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE res VARCHAR(5000) DEFAULT "";
DECLARE col VARCHAR(200);
DECLARE cur1 CURSOR FOR
select COLUMN_NAME from information_schema.columns
where TABLE_NAME=#table AND TABLE_SCHEMA="yourdatabase" ORDER BY ORDINAL_POSITION;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cur1;
REPEAT
FETCH cur1 INTO col;
IF NOT done THEN
set res = CONCAT(res,IF(LENGTH(res)>0,",",""),col);
END IF;
UNTIL done END REPEAT;
CLOSE cur1;
RETURN res;
Your result returns a comma delimited string, for example...
col1,col2,col3,col4,...col53
I agree that it isn't sufficient to Select *, if that one you don't need, as mentioned elsewhere, is a BLOB, you don't want to have that overhead creep in.
I would create a view with the required data, then you can Select * in comfort --if the database software supports them. Else, put the huge data in another table.
At first I thought you could use regular expressions, but as I've been reading the MYSQL docs it seems you can't. If I were you I would use another language (such as PHP) to generate a list of columns you want to get, store it as a string and then use that to generate the SQL.
Based on #Mahomedalid answer, I have done some improvements to support "select all columns except some in mysql"
SET #database = 'database_name';
SET #tablename = 'table_name';
SET #cols2delete = 'col1,col2,col3';
SET #sql = CONCAT(
'SELECT ',
(
SELECT GROUP_CONCAT( IF(FIND_IN_SET(COLUMN_NAME, #cols2delete), NULL, COLUMN_NAME ) )
FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = #tablename AND TABLE_SCHEMA = #database
),
' FROM ',
#tablename);
SELECT #sql;
If you do have a lots of cols, use this sql to change group_concat_max_len
SET ##group_concat_max_len = 2048;
I agree with #Mahomedalid's answer, but I didn't want to do something like a prepared statement and I didn't want to type all the fields, so what I had was a silly solution.
Go to the table in phpmyadmin->sql->select, it dumps the query: copy, replace and done! :)
While I agree with Thomas' answer (+1 ;)), I'd like to add the caveat that I'll assume the column that you don't want contains hardly any data. If it contains enormous amounts of text, xml or binary blobs, then take the time to select each column individually. Your performance will suffer otherwise. Cheers!
Just do
SELECT * FROM table WHERE whatever
Then drop the column in you favourite programming language: php
while (($data = mysql_fetch_array($result, MYSQL_ASSOC)) !== FALSE) {
unset($data["id"]);
foreach ($data as $k => $v) {
echo"$v,";
}
}
The answer posted by Mahomedalid has a small problem:
Inside replace function code was replacing "<columns_to_delete>," by "", this replacement has a problem if the field to replace is the last one in the concat string due to the last one doesn't have the char comma "," and is not removed from the string.
My proposal:
SET #sql = CONCAT('SELECT ', (SELECT REPLACE(GROUP_CONCAT(COLUMN_NAME),
'<columns_to_delete>', '\'FIELD_REMOVED\'')
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = '<table>'
AND TABLE_SCHEMA = '<database>'), ' FROM <table>');
Replacing <table>, <database> and `
The column removed is replaced by the string "FIELD_REMOVED" in my case this works because I was trying to safe memory. (The field I was removing is a BLOB of around 1MB)
You can use SQL to generate SQL if you like and evaluate the SQL it produces. This is a general solution as it extracts the column names from the information schema. Here is an example from the Unix command line.
Substituting
MYSQL with your mysql command
TABLE with the table name
EXCLUDEDFIELD with excluded field name
echo $(echo 'select concat("select ", group_concat(column_name) , " from TABLE") from information_schema.columns where table_name="TABLE" and column_name != "EXCLUDEDFIELD" group by "t"' | MYSQL | tail -n 1) | MYSQL
You will really only need to extract the column names in this way only once to construct the column list excluded that column, and then just use the query you have constructed.
So something like:
column_list=$(echo 'select group_concat(column_name) from information_schema.columns where table_name="TABLE" and column_name != "EXCLUDEDFIELD" group by "t"' | MYSQL | tail -n 1)
Now you can reuse the $column_list string in queries you construct.
I wanted this too so I created a function instead.
public function getColsExcept($table,$remove){
$res =mysql_query("SHOW COLUMNS FROM $table");
while($arr = mysql_fetch_assoc($res)){
$cols[] = $arr['Field'];
}
if(is_array($remove)){
$newCols = array_diff($cols,$remove);
return "`".implode("`,`",$newCols)."`";
}else{
$length = count($cols);
for($i=0;$i<$length;$i++){
if($cols[$i] == $remove)
unset($cols[$i]);
}
return "`".implode("`,`",$cols)."`";
}
}
So how it works is that you enter the table, then a column you don't want or as in an array: array("id","name","whatevercolumn")
So in select you could use it like this:
mysql_query("SELECT ".$db->getColsExcept('table',array('id','bigtextcolumn'))." FROM table");
or
mysql_query("SELECT ".$db->getColsExcept('table','bigtextcolumn')." FROM table");
May be I have a solution to Jan Koritak's pointed out discrepancy
SELECT CONCAT('SELECT ',
( SELECT GROUP_CONCAT(t.col)
FROM
(
SELECT CASE
WHEN COLUMN_NAME = 'eid' THEN NULL
ELSE COLUMN_NAME
END AS col
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'employee' AND TABLE_SCHEMA = 'test'
) t
WHERE t.col IS NOT NULL) ,
' FROM employee' );
Table :
SELECT table_name,column_name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'employee' AND TABLE_SCHEMA = 'test'
================================
table_name column_name
employee eid
employee name_eid
employee sal
================================
Query Result:
'SELECT name_eid,sal FROM employee'
I use this work around although it may be "Off topic" - using mysql workbench and the query builder -
Open the columns view
Shift select all the columns you want in your query (in your case all but one which is what i do)
Right click and select send to SQL Editor-> name short.
Now you have the list and you can then copy paste the query to where ever.
If it's always the same one column, then you can create a view that doesn't have it in it.
Otherwise, no I don't think so.
I would like to add another point of view in order to solve this problem, specially if you have a small number of columns to remove.
You could use a DB tool like MySQL Workbench in order to generate the select statement for you, so you just have to manually remove those columns for the generated statement and copy it to your SQL script.
In MySQL Workbench the way to generate it is:
Right click on the table -> send to Sql Editor -> Select All Statement.
The accepted answer has several shortcomings.
It fails where the table or column names requires backticks
It fails if the column you want to omit is last in the list
It requires listing the table name twice (once for the select and another for the query text) which is redundant and unnecessary
It can potentially return column names in the wrong order
All of these issues can be overcome by simply including backticks in the SEPARATOR for your GROUP_CONCAT and using a WHERE condition instead of REPLACE(). For my purposes (and I imagine many others') I wanted the column names returned in the same order that they appear in the table itself. To achieve this, here we use an explicit ORDER BY clause inside of the GROUP_CONCAT() function:
SELECT CONCAT(
'SELECT `',
GROUP_CONCAT(COLUMN_NAME ORDER BY `ORDINAL_POSITION` SEPARATOR '`,`'),
'` FROM `',
`TABLE_SCHEMA`,
'`.`',
TABLE_NAME,
'`;'
)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE `TABLE_SCHEMA` = 'my_database'
AND `TABLE_NAME` = 'my_table'
AND `COLUMN_NAME` != 'column_to_omit';
I have a suggestion but not a solution.
If some of your columns have a larger data sets then you should try with following
SELECT *, LEFT(col1, 0) AS col1, LEFT(col2, 0) as col2 FROM table
If you use MySQL Workbench you can right-click your table and click Send to sql editor and then Select All Statement This will create an statement where all fields are listed, like this:
SELECT `purchase_history`.`id`,
`purchase_history`.`user_id`,
`purchase_history`.`deleted_at`
FROM `fs_normal_run_2`.`purchase_history`;
SELECT * FROM fs_normal_run_2.purchase_history;
Now you can just remove those that you dont want.

Get column from a table dynamically on basis of input parameter

I want to create a stored procedure in which I will pass an id and I want to select a column on basis of it.
Suppose my table has columns namely - id, theme1, theme2, theme3, theme4, theme5 etc.
I need a query which will select the column on basis of my input. Like if I pass id = 3 then it should give theme3 column as result.
Is there any way possible for this type of dynamic query?
Suppose my table has columns namely - id, theme1, theme2, theme3, theme4, theme5 etc.
If you can change this you really should...
Whenever you feel the need to set a number to a column's name (like Tel1, Tel2 or Theme1, Theme2) this is a very strong hint for a bad design...
If possible try something like
CREATE TABLE Theme(ThemeID INT IDENTITY, ForeignID INT, ThemeRank INT, ThemeName VARCHAR(100));
SELECT *
FROM YourTable AS yt
INNER JOIN Theme AS th ON yt.ForeignID=th.ForeignID AND ThemeRank=#passedInValue;
To answer your question: The only way to do this is dynamically created SQL and I would really not recommend it! This is a very bad approach...
UPDATE Just to be complete:
DECLARE #passedInId INT=3;
DECLARE #cmd VARCHAR(MAX)='SELECT Theme' + CAST(#passedInId AS VARCHAR(MAX)) + ' FROM YourTable WHERE ...';
EXEC(#cmd);
This will create a SQL command dynamically and execute it. The problems are
no ad-hoc / inline approach
The usage of the retrieved result is - uhm - cumbersome...
I think this will help you,
Ordinal_Position will help you to find the column details
SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_DEFAULT
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'tbl_name'
AND ORDINAL_POSITION = 2
https://www.mssqltips.com/sqlservertutorial/183/informationschemacolumns/

How to select all the columns of a table except one column?

How to select all the columns of a table except one column?
I have nearly 259 columns I cant mention 258 columns in SELECT statement.
Is there any other way to do it?
You can use this approach to get the data from all the columns except one:-
Insert all the data into a temporary table
Then drop the column which you dont want from the temporary table
Fetch the data from the temporary table(This will not contain the data of the removed column)
Drop the temporary table
Something like this:
SELECT * INTO #TemporaryTable FROM YourTableName
ALTER TABLE #TemporaryTable DROP COLUMN Columnwhichyouwanttoremove
SELECT * FROM #TemporaryTable
DROP TABLE #TemporaryTable
Create a view. Yes, in the view creation statement, you will have to list each...and...every...field...by...name.
Once.
Then just select * from viewname after that.
This is not a generic solution, but some databases allow you to use regular expressions to specify the columns.
For instance, in the case of Hive, the following query selects all columns except ds and hr:
SELECT `(ds|hr)?+.+` FROM sales
You can get the column name details from sys.columns table
Try the following query:
SELECT * FROM SYS.COLUMNS
WHERE object_id = OBJECT_ID('dbo.TableName')
AND [Name] <> 'ColumnName'
DECLARE #sql as VARCHAR(8000)
SET #sql = 'SELECT '
SELECT #sql += [Name] + ', ' FROM SYS.COLUMNS
WHERE object_id = OBJECT_ID('dbo.TableName')
AND [Name] <> 'ColumnName'
SELECT #sql += ' FROM Dbo.TableName'
EXEC(#sql)
I just wanted to echo #Luann's comment as I use this approach always.
Just right click on the table > Script table as > Select to > New Query window.
You will see the select query. Just take out the column you want to exclude and you have your preferred select query.
There are lot of options available , one of them is :
CREATE TEMPORARY TABLE temp_tb SELECT * FROM orig_tb;
ALTER TABLE temp_tb DROP col_x;
SELECT * FROM temp_tb;
Here the col_x is the column which u dont want to include in select statement.
Take a look at this question : Select all columns except one in MySQL?
You can retrieve the list of column name by simple query and then remove those column by apply where query like this.
SELECT * FROM (
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = N'TableName'
) AS allColumns
WHERE allColumns.COLUMN_NAME NOT IN ('unwantedCol1', 'unwantedCol2')
If you are using DataGrip you can do the following:
Enter your SELECT statement SELECT * FROM <your_table>;
Put your cursor over * and press Alt+Enter
You will get pop up menu with Expand column list option
Click on it and it will convert * with full list of columns
Now you can remove columns that you don't need
Here is a link for an example on how to do it.
Without creating new table you can do simply (e.g with mysqli):
get all columns
loop through all columns and remove wich you want
make your query
$r = mysqli_query('SELECT column_name FROM information_schema.columns WHERE table_name = table_to_query');
$c = count($r); while($c--) if($r[$c]['column_name'] != 'column_to_remove_from_query') $a[] = $r[$c]['column_name']; else unset($r[$c]);
$r = mysqli_query('SELECT ' . implode(',', $a) . ' FROM table_to_query');
Try the following query:
DECLARE #Temp NVARCHAR(MAX);
DECLARE #SQL NVARCHAR(MAX);
SET #Temp = '';
SELECT #Temp = #Temp + COLUMN_NAME + ', ' FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME ='Person' AND COLUMN_NAME NOT IN ('Id')
SET #SQL = 'SELECT ' + SUBSTRING(#Temp, 0, LEN(#Temp)) +' FROM [Person]';
EXECUTE SP_EXECUTESQL #SQL;
In your case, expand columns of that database in the object explorer. Drag the columns in to the query area.
And then just delete one or two columns which you don't want and then run it. I'm open to any suggestions easier than this.
Only one way to achieve this giving column name. There is no other method found. You must have to list all column name

How to select some particular columns from a table if the table has more than 100 columns

I need to select 90 columns out of 107 columns from my table.
Is it possible to write select * except( column1,column2,..) from table or any other way to get specific columns only, or I need to write all the 90 columns in select statement?
You could generate the column list:
select name + ', '
from sys.columns
where object_id = object_id('YourTable')
and name not in ('column1', 'column2')
It's possible to do this on the fly with dynamic SQL:
declare #columns varchar(max)
select #columns = case when #columns is null then '' else #columns + ', ' end +
quotename(name)
from sys.columns
where object_id = object_id('YourTable')
and name not in ('column1', 'column2')
declare #query varchar(max)
set #query = 'select ' + #columns + ' from YourTable'
exec (#query)
No, there's no way of doing * EXCEPT some columns. SELECT * itself should rarely, if ever, be used outside of EXISTS tests.
If you're using SSMS, you can drag the "columns" folder (under a table) from the Object Explorer into a query window, and it will insert all of the column names (so you can then go through them and remove the 17 you don't want)
There is no way in SQL to do select everything EXCEPT col1, col2 etc.
The only way to do this is to have your application handle this, and generate the sql query dynamically.
You could potentially do some dynamic sql for this, but it seems like overkill. Also it's generally considered poor practice to use SELECT *... much less SELECT * but not col3, col4, col5 since you won't get consistent results in the case of table changes.
Just use SSMS to script out a select statement and delete the columns you don't need. It should be simple.
No - you need to write all columns you need. You might create an view for that, so your actual statement could use select * (but then you have to list all columns in the view).
Since you should never be using select *, why is this a problem? Just drag the columns over from the Object Explorer and delete the ones you don't want.

Exclude a column using SELECT * [except columnA] FROM tableA?

We all know that to select all columns from a table, we can use
SELECT * FROM tableA
Is there a way to exclude column(s) from a table without specifying all the columns?
SELECT * [except columnA] FROM tableA
The only way that I know is to manually specify all the columns and exclude the unwanted column. This is really time consuming so I'm looking for ways to save time and effort on this, as well as future maintenance should the table has more/less columns.
You can try it this way:
/* Get the data into a temp table */
SELECT * INTO #TempTable
FROM YourTable
/* Drop the columns that are not needed */
ALTER TABLE #TempTable
DROP COLUMN ColumnToDrop
/* Get results and drop temp table */
SELECT * FROM #TempTable
DROP TABLE #TempTable
No.
Maintenance-light best practice is to specify only the required columns.
At least 2 reasons:
This makes your contract between client and database stable. Same data, every time
Performance, covering indexes
Edit (July 2011):
If you drag from Object Explorer the Columns node for a table, it puts a CSV list of columns in the Query Window for you which achieves one of your goals
If you don't want to write each column name manually you can use Script Table As by right clicking on table or view in SSMS like this:
Then you will get whole select query in New Query Editor Window then remove unwanted column like this:
Done
The automated way to do this in SQL (SQL Server) is:
declare #cols varchar(max), #query varchar(max);
SELECT #cols = STUFF
(
(
SELECT DISTINCT '], [' + name
FROM sys.columns
where object_id = (
select top 1 object_id from sys.objects
where name = 'MyTable'
)
and name not in ('ColumnIDontWant1', 'ColumnIDontWant2')
FOR XML PATH('')
), 1, 2, ''
) + ']';
SELECT #query = 'select ' + #cols + ' from MyTable';
EXEC (#query);
A modern SQL dialect like BigQuery proposes an excellent solution.
SELECT * EXCEPT(ColumnNameX, [ColumnNameY, ...])
FROM TableA
This is a very powerful SQL syntax to avoid a long list of columns that need to be updated all the time due to table column name changes. And this functionality is missing in the current SQL Server implementation, which is a pity. Hopefully, one day, Microsoft Azure will be more data scientist-friendly.
Data scientists like to have a quick option to shorten a query and remove some columns (due to duplication or any other reason).
https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#select-modifiers
You could create a view that has the columns you wish to select, then you can just select * from the view...
Yes it's possible (but not recommended).
CREATE TABLE contact (contactid int, name varchar(100), dob datetime)
INSERT INTO contact SELECT 1, 'Joe', '1974-01-01'
DECLARE #columns varchar(8000)
SELECT #columns = ISNULL(#columns + ', ','') + QUOTENAME(column_name)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'contact' AND COLUMN_NAME <> 'dob'
ORDER BY ORDINAL_POSITION
EXEC ('SELECT ' + #columns + ' FROM contact')
Explanation of the code:
Declare a variable to store a comma separated list of column names. This defaults to NULL.
Use a system view to determine the names of the columns in our table.
Use SELECT #variable = #variable + ... FROM to concatenate the
column names. This type of SELECT does not not return a result set. This is perhaps undocumented behaviour but works in every version of SQL Server. As an alternative you could use SET #variable = (SELECT ... FOR XML PATH('')) to concatenate strings.
Use the ISNULL function to prepend a comma only if this is not the
first column name.
Use the QUOTENAME function to support spaces and punctuation in column names.
Use the WHERE clause to hide columns we don't want to see.
Use EXEC (#variable), also known as dynamic SQL, to resolve the
column names at runtime. This is needed because we don't know the column names at compile time.
Like the others have said there is no way to do this, but if you're using Sql Server a trick that I use is to change the output to comma separated, then do
select top 1 * from table
and cut the whole list of columns from the output window. Then you can choose which columns you want without having to type them all in.
Basically, you cannot do what you would like - but you can get the right tools to help you out making things a bit easier.
If you look at Red-Gate's SQL Prompt, you can type "SELECT * FROM MyTable", and then move the cursor back after the "*", and hit <TAB> to expand the list of fields, and remove those few fields you don't need.
It's not a perfect solution - but a darn good one! :-) Too bad MS SQL Server Management Studio's Intellisense still isn't intelligent enough to offer this feature.......
Marc
DECLARE #SQL VARCHAR(max), #TableName sysname = 'YourTableName'
SELECT #SQL = COALESCE(#SQL + ', ', '') + Name
FROM sys.columns
WHERE OBJECT_ID = OBJECT_ID(#TableName)
AND name NOT IN ('Not This', 'Or that');
SELECT #SQL = 'SELECT ' + #SQL + ' FROM ' + #TableName
EXEC (#SQL)
UPDATE:
You can also create a stored procedure to take care of this task if you use it more often.
In this example I have used the built in STRING_SPLIT() which is available on SQL Server 2016+,
but if you need there are pleanty of examples of how to create it manually on SO.
CREATE PROCEDURE [usp_select_without]
#schema_name sysname = N'dbo',
#table_name sysname,
#list_of_columns_excluded nvarchar(max),
#separator nchar(1) = N','
AS
BEGIN
DECLARE
#SQL nvarchar(max),
#full_table_name nvarchar(max) = CONCAT(#schema_name, N'.', #table_name);
SELECT #SQL = COALESCE(#SQL + ', ', '') + QUOTENAME([Name])
FROM sys.columns sc
LEFT JOIN STRING_SPLIT(#list_of_columns_excluded, #separator) ss ON sc.[name] = ss.[value]
WHERE sc.OBJECT_ID = OBJECT_ID(#full_table_name, N'u')
AND ss.[value] IS NULL;
SELECT #SQL = N'SELECT ' + #SQL + N' FROM ' + #full_table_name;
EXEC(#SQL)
END
And then just:
EXEC [usp_select_without]
#table_name = N'Test_Table',
#list_of_columns_excluded = N'ID, Date, Name';
no there is no way to do this. maybe you can create custom views if that's feasible in your situation
EDIT May be if your DB supports execution of dynamic sql u could write an SP and pass the columns u don't want to see to it and let it create the query dynamically and return the result to you. I think this is doable in SQL Server atleast
If you are using SQL Server Management Studio then do as follows:
Type in your desired tables name and select it
Press Alt+F1
o/p shows the columns in table.
Select the desired columns
Copy & paste those in your select query
Fire the query.
Enjoy.
If you want to exclude a sensitive case column like the password for example, I do this to hide the value :
SELECT * , "" as password FROM tableName;
The best way to solve this is using view you can create view with required columns and retrieve data form it
example
mysql> SELECT * FROM calls;
+----+------------+---------+
| id | date | user_id |
+----+------------+---------+
| 1 | 2016-06-22 | 1 |
| 2 | 2016-06-22 | NULL |
| 3 | 2016-06-22 | NULL |
| 4 | 2016-06-23 | 2 |
| 5 | 2016-06-23 | 1 |
| 6 | 2016-06-23 | 1 |
| 7 | 2016-06-23 | NULL |
+----+------------+---------+
7 rows in set (0.06 sec)
mysql> CREATE VIEW C_VIEW AS
-> SELECT id,date from calls;
Query OK, 0 rows affected (0.20 sec)
mysql> select * from C_VIEW;
+----+------------+
| id | date |
+----+------------+
| 1 | 2016-06-22 |
| 2 | 2016-06-22 |
| 3 | 2016-06-22 |
| 4 | 2016-06-23 |
| 5 | 2016-06-23 |
| 6 | 2016-06-23 |
| 7 | 2016-06-23 |
+----+------------+
7 rows in set (0.00 sec)
In summary you cannot do it, but I disagree with all of the comment above, there "are" scenarios where you can legitimately use a *
When you create a nested query in order to select a specific range out of a whole list (such as paging) why in the world would want to specify each column on the outer select statement when you have done it in the inner?
In SQL Management Studio you can expand the columns in Object Explorer, then drag the Columns tree item into a query window to get a comma separated list of columns.
If we are talking of Procedures, it works with this trick to generate a new query and EXECUTE IMMEDIATE it:
SELECT LISTAGG((column_name), ', ') WITHIN GROUP (ORDER BY column_id)
INTO var_list_of_columns
FROM ALL_TAB_COLUMNS
WHERE table_name = 'PUT_HERE_YOUR_TABLE'
AND column_name NOT IN ('dont_want_this_column','neither_this_one','etc_column');
Postgres sql has a way of doing it
pls refer:
http://www.postgresonline.com/journal/archives/41-How-to-SELECT-ALL-EXCEPT-some-columns-in-a-table.html
The Information Schema Hack Way
SELECT 'SELECT ' || array_to_string(ARRAY(SELECT 'o' || '.' || c.column_name
FROM information_schema.columns As c
WHERE table_name = 'officepark'
AND c.column_name NOT IN('officeparkid', 'contractor')
), ',') || ' FROM officepark As o' As sqlstmt
The above for my particular example table - generates an sql statement that looks like this
SELECT o.officepark,o.owner,o.squarefootage
FROM officepark As o
Is there a way to exclude column(s) from a table without specifying
all the columns?
Using declarative SQL in the usual way, no.
I think your proposed syntax is worthy and good. In fact, the relational database language 'Tutorial D' has a very similar syntax where the keywords ALL BUT are followed by a set of attributes (columns).
However, SQL's SELECT * already gets a lot a flak (#Guffa's answer here is a typical objection), so I don't think SELECT ALL BUT will get into the SQL Standard anytime soon.
I think the best 'work around' is to create a VIEW with only the columns you desire then SELECT * FROM ThatView.
I do not know of any database that supports this (SQL Server, MySQL, Oracle, PostgreSQL). It is definitely not part of the SQL standards so I think you have to specify only the columns you want.
You could of course build your SQL statement dynamically and have the server execute it. But this opens up the possibility for SQL injection..
Right click table in Object Explorer, Select top 1000 rows
It'll list all columns and not *. Then remove the unwanted column(s). Should be much faster than typing it yourself.
Then when you feel this is a bit too much work, get Red Gate's SQL Prompt, and type ssf from tbl, go to the * and click tab again.
I know this is a little old, but I had just run into the same issue and was looking for an answer. Then I had a senior developer show me a very simple trick.
If you are using the management studio query editor, expand the database, then expand the table that you are selecting from so that you can see the columns folder.
In your select statement, just highlight the referenced columns folder above and drag and drop it into the query window. It will paste all of the columns of the table, then just simply remove the identity column from the list of columns...
A colleage advised a good alternative:
Do SELECT INTO in your preceding query (where you generate or get the
data from) into a table (which you will delete when done). This will
create the structure for you.
Do a script as CREATE to new query
window.
Remove the unwanted columns. Format the remaining columns
into a 1 liner and paste as your column list.
Delete the table you
created.
Done...
This helped us a lot.
Actually snowflake just released exclude so now you'd just:
SELECT * EXCLUDE [columnA,columnB,...] FROM tableA
Well, it is a common best practice to specify which columns you want, instead of just specifying *. So you should just state which fields you want your select to return.
That what I use often for this case:
declare #colnames varchar(max)=''
select #colnames=#colnames+','+name from syscolumns where object_id(tablename)=id and name not in (column3,column4)
SET #colnames=RIGHT(#colnames,LEN(#colnames)-1)
#colnames looks like column1,column2,column5
I did it like this and it works just fine (version 5.5.41):
# prepare column list using info from a table of choice
SET #dyn_colums = (SELECT REPLACE(
GROUP_CONCAT(`COLUMN_NAME`), ',column_name_to_remove','')
FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE
`TABLE_SCHEMA`='database_name' AND `TABLE_NAME`='table_name');
# set sql command using prepared columns
SET #sql = CONCAT("SELECT ", #dyn_colums, " FROM table_name");
# prepare and execute
PREPARE statement FROM #sql;
EXECUTE statement;
Sometimes the same program must handle different database stuctures. So I could not use a column list in the program to avoid errors in select statements.
* gives me all the optional fields. I check if the fields exist in the data table before use. This is my reason for using * in select.
This is how I handle excluded fields:
Dim da As New SqlDataAdapter("select * from table", cn)
da.FillSchema(dt, SchemaType.Source)
Dim fieldlist As String = ""
For Each DC As DataColumn In DT.Columns
If DC.ColumnName.ToLower <> excludefield Then
fieldlist = fieldlist & DC.Columnname & ","
End If
Next
In Hive Sql you can do this:
set hive.support.quoted.identifiers=none;
select
`(unwanted_col1|unwanted_col2|unwanted_col3)?+.+`
from database.table
this gives you the rest cols
The proposed answer (stored procedure) from BartoszX didn't work for me when using a view instead of a real table.
Credit for the idea and the code below (except for my fix) belongs to BartoszX.
In order that this works for tables as well as for views, use the following code:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[select_without]
#schema_name sysname = N'dbo',
#table_name sysname,
#list_of_columns_excluded nvarchar(max),
#separator nchar(1) = N','
AS
BEGIN
DECLARE
#SQL nvarchar(max),
#full_table_name nvarchar(max) = CONCAT(#schema_name, N'.', #table_name);
SELECT #SQL = COALESCE(#SQL + ', ', '') + QUOTENAME([Name])
FROM sys.columns sc
LEFT JOIN STRING_SPLIT(#list_of_columns_excluded, #separator) ss ON sc.[name] = ss.[value]
WHERE sc.OBJECT_ID = OBJECT_ID(#full_table_name)
AND ss.[value] IS NULL;
SELECT #SQL = N'SELECT ' + #SQL + N' FROM ' + #full_table_name;
EXEC(#SQL)
END
GO