SQL - Subquery (Column names) - sql

I need a select query thats returns the value of some columns.
The column that I want starts with 'U_S'.
Select * from em
I need to transform the query above. The '*' needs to be the result (but with commas) of:
select COLUMN_NAME from information_schema.columns
where table_name='em' and column_name like 'u_s%'

There are countless examples like this, but I understand that sometimes we all need a little kick-start.
Select Stuff((Select ',' +quotename(Column_Name)
From information_schema.columns
Where table_name='em' and column_name like 'u_s%'
For XML Path ('')),1,1,'')

you can use code like below:
declare #col varchar(500)
select #col=Stuff((Select ',' +quotename(Column_Name)
From information_schema.columns
Where table_name='em' and column_name like 'u_s%'
For XML Path ('')),1,1,'')
exec('select '+#col
+' from em')

select CAST(
(select COLUMN_NAME + ','
from information_schema.columns
where table_name='em' and column_name like 'u_s%'
for xml path('')
) as nvarchar(max)
)
you will have to delete last comma...

You can also select the column names directly into a variable, which can then be used for a Dynamic SQL.
declare #Cols varchar(max) = null;
select #Cols = concat(#Cols +', ',quotename(COLUMN_NAME))
from information_schema.columns
where table_name='em' and column_name like 'u_s%'
order by column_name;
--select #Cols as Cols;
declare #SQL varchar(max);
set #SQL = 'select '+ #Cols +' from em';
exec(#SQL);
#Cols is null at first, and null+',' gives null.
So the result won't start with a comma.
The quotename function is just added as a safety measure.
Just in case the columnnames sometimes have spaces in the name.

Related

Dynamically select columns in SQL

I have a question regarding the creation of a script to dynamically select columns for a select statement. Here is my scenario:
I have some tables that have columns that are called "text1-n", "value1-n", "checkbox1-n" etc. I want to check whether these columns have values stored and if so what data is stored. The Problem is that different tables have a different number of columns and not all tables have all of these columns.
So Table1 may have "text1", "text2", "value1", "value2",... while Table2 has only "text1-5".
To get the column names I use this statement:
DECLARE #table_name varchar(max) = '...';
SELECT
COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME LIKE #table_name
AND (COLUMN_NAME LIKE 'text%'
OR COLUMN_NAME LIKE 'combobox%'
OR COLUMN_NAME LIKE 'date%'
OR COLUMN_NAME LIKE 'checkbox%'
OR COLUMN_NAME LIKE 'value%');
The goal is to get a dynamically created statemant like
SELECT DISTINCT
Combobox1
,Combobox2
,Combobox3
,Combobox4
,Date1
,Date2
,Text1
,Text2
FROM ...
I've found a similar thread, but I don't understand the DynamicSQL part so that I can adopt it to my needs.
Hope someone can help me.
DECLARE #table_name varchar(max)
DECLARE #COLUMN_NAME varchar(max)
Declare cur22 Cursor FORWARD_ONLY READ_ONLY FOR
SELECT
Table_Name , COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE (COLUMN_NAME LIKE 'text%'
OR COLUMN_NAME LIKE 'combobox%'
OR COLUMN_NAME LIKE 'date%'
OR COLUMN_NAME LIKE 'checkbox%'
OR COLUMN_NAME LIKE 'value%');
OPEN cur22
FETCH NEXT FROM cur22
INTO #table_name , #COLUMN_NAME
while (##FETCH_STATUS = 0)
begin
EXEC('SELECT * FROM ' + #table_name + ' Where LEN(' + #COLUMN_NAME + ') > 0')
FETCH NEXT FROM cur22
INTO #table_name , #COLUMN_NAME
end
Close cur22
Deallocate cur22
A more lowtech solution would be to make a view per table that have all columns
SELECT DISTINCT
null as Combobox1
,Combobox2
,Combobox3
,null as Combobox4
,null as Date1
,null as Date2
,Text1
,Text2
FROM <tablename>
It may be a little annoying to maintain, but you will get code that is a lot easier to understand.
Just to close this thread... I could manage to create the desired statement/Script.
DECLARE #table_name varchar(max) = 'par_companygroup2';
DECLARE #SQL varchar(max);
SET #SQL =
'SELECT DISTINCT ' + (SELECT
p.*
FROM (SELECT
STUFF((SELECT
+',' +
Column_name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME LIKE #table_name
AND (
Column_name LIKE 'text%'
OR Column_name LIKE 'combobox%'
OR Column_name LIKE 'date%'
OR Column_name LIKE 'checkbox%'
OR Column_name LIKE 'value%'
)
ORDER BY 1 ASC
FOR XML PATH (''), TYPE)
.value('.', 'VARCHAR(MAX)'), 1, 1, '') AS Column_name) p)
+ ' FROM ' + #table_name
EXECUTE (#SQL)

Dynamically insert column names into function

I try to insert column names into my query to obtain the max-length of the underlying data-input, like:
DECLARE #cols AS varchar(MAX)
,#query AS nvarchar(MAX)
SELECT #cols = (
select STRING_AGG(COLUMN_NAME, ',')
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME='mytbl'
and TABLE_SCHEMA = 'dbo'
and DATA_TYPE = 'varchar'
)
set #query = 'select top(1) max(datalength(' + #cols + ')) FROM dbo.mytbl'
exec sp_executesql #query;
.. which prompts the following error:
The datalength function requires 1 argument(s).
I donĀ“t know how to cast the string so that the #cols are recognized by the encasing max(datalength()) function(s).
Any ideas how to circumvent this error? I am out of ideas.
UPDATE:
The intended output should look something like that:
select max(datalength(col1))
,max(datalength(col2))
,max(datalength(col3))
,max(datalength(col4))
...
from dbo.mytable
which works and gives me the max-char of any input per column, like:
you need to apply the MAX() and DATALENGTH() on the column before concatenation
Change the #cols to
SELECT #cols = (
select STRING_AGG('MAX(DATALENGTH(' + COLUMN_NAME + '))', ',')
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME='mytbl'
and TABLE_SCHEMA = 'dbo'
and DATA_TYPE = 'varchar'
)
and the final #query is just a simple select
set #query = 'select ' + #cols + ' FROM dbo.mytbl'
You should print out the query for inspection, before execute it
print #query

SQL results to string with wildcard

Suppose you have a table like this:
ID FNAME LNAME
1 Bob Smith
2 Sally Jones
A simple SELECT * FROM [Table] will return all rows. But what if you wanted to build a single string out of the results, and the column names are unknown? In other words, this will not work:
SELECT ID + ',' + FNAME + ',' + LNAME FROM [Table]
because you don't know the column names. Additionally, COALESCE won't work because it doesn't accept wildcards. Ideally you want to execute something like this:
SELECT dbo.FunctionThatSplitsResultsToString(*) FROM [Table]
and have it return
1,Bob,Smith
2,Sally,Jones
Is this possible?
This is a corrected version of the answer #Igor gave. In addition to concatenating comma characters between the values, it converts NULL values to an empty string (because concatenating a string to NULL results in a NULL value).
DECLARE #sql NVARCHAR(max)='SELECT '
DECLARE #TableName NVARCHAR(max) = 'Table_Name' -- <-- Set the target table name here
SELECT #sql=#sql+N'ISNULL(CAST(' + name +' as NVARCHAR(max)), '''')+'',''+'
FROM sys.columns
WHERE object_id=OBJECT_ID(#TableName)
SELECT #sql=SUBSTRING(#sql,1,LEN(#sql)-5)+N' FROM ' + #TableName
--SELECT #sql -- uncomment to see the query string
EXEC sp_executesql #sql
As the first Igor noted, the solution is dynamic SQL. You need to construct the underlying SQL statement correctly.
The following code casts all columns to varchar() and then concatenates them together. The final form of the SQL removes the last "+" sign and adds the from statement:
declare #sql varchar(max);
select #sql = (select 'cast('+coalesce(column_name, '') + ' as varchar(255)) +'
from information_schema.columns
where table_name = <whatever>
for xml path ('')
);
select #sql = left(#sql, len(#sql - 2)) + ' from t';
exec(#sql);
I admit to being US-centric and rarely using internationalization. The whole thing also works with nvarchars().
Try the below one
GO
DECLARE #ColumnsList VARCHAR(MAX), #SelectStatement VARCHAR(MAX),#TargetTable VARCHAR(250) ,#FINALSQL NVARCHAR(MAX)
SET #TARGETTABLE ='TempData'
SELECT #ColumnsList = COALESCE( #ColumnsList+' + '','' +' ,'') + 'Cast('+ A.COLUMN_NAME + ' AS Varchar(250))'
FROM (select Column_Name from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME= #TARGETTABLE) A
SELECT #FinalSql = 'Select ' +#ColumnsList + ' FROM ' + #TARGETTABLE
EXEC SP_EXECUTESQL #FINALSQL
GO

SQL Wildcard instead of key in SELECT statement

Can I, in a neat way do:
SELECT *
FROM tablename
WHERE * LIKE '%something%';
Without having to do:
SELECT *
FROM tablename
WHERE ColA LIKE '%something%'
OR ColB LIKE '%something%' ...;
Running SQL Server 2008, I get error:
"Cannot use a CONTAINS or FREETEXT predicate on table or indexed view
'tablename' because it is not full-text indexed.
I don't have full text index :)
To build on #Bob Probst's idea, you might try dynamic SQL like this:
-- Set these!
declare #tableName nvarchar(128)= 'MyTableName'
declare #searchString nvarchar(max)= '%something%'
-- Build SQL query
declare #sql nvarchar(max)
select #sql = isnull(#sql + 'or ', 'select * from ' + #tableName + ' where ' )
+ '[' + column_name + '] like ''' + replace(#searchString, '''', '''''') + ''' '
from information_schema.columns
where table_name = #tableName
-- Could use this where clause for only comparing string fields (or eliminating image and such)
--and data_type in ('varchar', 'char','nvarchar', 'nchar')
-- Run SQL query
print (#sql) -- For debug
exec (#sql)
You could script it like this:
select 'select * from dbo.ACCOUNT_DIMENSION where '
union all
select c.name+' like ''%something%'' or '
from sys.tables t
inner join sys.columns c on (t.object_id=c.object_id)
where t.name = 'ACCOUNT_DIMENSION'
union all
select '1=1'
No. This is not possible. You have to write the fieldnames.
You should be able to use the + sign to bind ColA and ColB together:
SELECT
*
FROM
tablename
WHERE
ColA+ColB Like '%something%'
How's CONTAINS* sound?
Use AdventureWorks2008R2;
GO
SELECT Name, Color FROM Production.Product
WHERE CONTAINS((Name, Color), 'Red');
*This requires fulltext indices
Without a fulltext index the only way to do this dynamically is with a dynamically built statement;
declare #sql varchar(max) = 'select * from tablename where 1=0'
select #sql += ' or ' + quotename(column_name) + ' like ''%something%'''
from information_schema.columns
where TABLE_NAME = 'tablename'
and data_type in ('char', 'varchar', 'nchar', 'nvarchar')
exec(#sql)

sql select with column name like

I have a table with column names a1,a2...,b1.b2....
How can I select all those with column names like a%?
This will get you the list
select * from information_schema.columns
where table_name='table1' and column_name like 'a%'
If you want to use that to construct a query, you could do something like this:
declare #sql nvarchar(max)
set #sql = 'select '
select #sql = #sql + '[' + column_name +'],'
from information_schema.columns
where table_name='table1' and column_name like 'a%'
set #sql = left(#sql,len(#sql)-1) -- remove trailing comma
set #sql = #sql + ' from table1'
exec sp_executesql #sql
Note that the above is written for SQL Server.
You need to use view INFORMATION_SCHEMA.COLUMNS
select COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = my_table_name AND COLUMN_NAME like 'a%'
TO inline rows you can use PIVOT and for execution EXEC() function.
This will show you the table name and column name
select table_name,column_name from information_schema.columns
where column_name like '%breakfast%'
SELECT * FROM SysColumns WHERE Name like 'a%'
Will get you a list of columns, you will want to filter more to restrict it to your target table
From there you can construct some ad-hoc sql
Here is a nice way to display the information that you want:
SELECT B.table_catalog as 'Database_Name',
B.table_name as 'Table_Name',
stuff((select ', ' + A.column_name
from INFORMATION_SCHEMA.COLUMNS A
where A.Table_name = B.Table_Name
FOR XML PATH(''),TYPE).value('(./text())[1]','NVARCHAR(MAX)')
, 1, 2, '') as 'Columns'
FROM INFORMATION_SCHEMA.COLUMNS B
WHERE B.TABLE_NAME like '%%'
AND B.COLUMN_NAME like '%%'
GROUP BY B.Table_Catalog, B.Table_Name
Order by 1 asc
Add anything between either '%%' in the main select to narrow down what tables and/or column names you want.
You cannot with standard SQL. Column names are not treated like data in SQL.
If you use a SQL engine that has, say, meta-data tables storing column names, types, etc. you may select on that table instead.
Blorgbeard had a great answer for SQL server. If you have a MySQL server like mine then the following will allow you to select the information from columns where the name is like some key phrase. You just have to substitute the table name, database name, and keyword.
SET #columnnames = (SELECT concat("`",GROUP_CONCAT(`COLUMN_NAME` SEPARATOR "`, `"),"`")
FROM `INFORMATION_SCHEMA`.`COLUMNS`
WHERE `TABLE_SCHEMA`='your_database'
AND `TABLE_NAME`='your_table'
AND COLUMN_NAME LIKE "%keyword%");
SET #burrito = CONCAT("SELECT ",#columnnames," FROM your_table");
PREPARE result FROM #burrito;
EXECUTE result;
Thank you #Blorgbeard for the genious idea.
By the way Blorgbeard's query was not working for me so I edited it:
DECLARE #Table_Name as VARCHAR(50) SET #Table_Name = 'MyTable' -- put here you table name
DECLARE #Column_Like as VARCHAR(20) SET #Column_Like = '%something%' -- put here you element
DECLARE #sql NVARCHAR(MAX) SET #sql = 'select '
SELECT #sql = #sql + '[' + sys.columns.name + '],'
FROM sys.columns
JOIN sys.tables ON sys.columns.object_id = tables.object_id
WHERE sys.columns.name like #Column_Like
and sys.tables.name = #Table_Name
SET #sql = left(#sql,len(#sql)-1) -- remove trailing comma
SET #sql = #sql + ' from ' + #Table_Name
EXEC sp_executesql #sql