I am trying to create a dynamic SQL statement that includes an alias that has to increment. My query is like
DECLARE #q varchar(255)
SET #q = '0'
SELECT 'SELECT (SELECT DISTINCT NameColumn
FROM NAMETABLE) #q'
FROM NameTable
Where for each record in nametable #q changes. So it would go #q = 0 for record 1, #q = 1 for record 2, #q = 2 for record 3, etc. I found ROW_NUMBER but that appears to only do incrementing a column and as an Int whereas I need a varchar to increment. If someone had an idea as to how to do this or could point me in the right direction that would be wonderful
Is this what you want?
SELECT 'SELECT (SELECT DISTINCT NameColumn
FROM NAMETABLE
) ' + cast(row_number() over (order by (select NULL)) as varchar(255))
FROM NameTable;
I am, however, unclear on why you would want an alias to be a number.
EDIT:
To get what you want, just pre-pend the number with a letter.
SELECT 'SELECT (SELECT DISTINCT NameColumn
FROM NAMETABLE
) t' + cast(row_number() over (order by (select NULL)) as varchar(255))
FROM NameTable;
Related
Well, I have a number which stored in a column. If I want to divide the value, I just need:
select columnName / 12 from myTable
Is it possible to put the result into 12 column? I want to make the 12 is flexible. So for instance, if I divide the value by 4, so the result should be 4 column.
Value Result1 Result2 Result3 Result4
12000 3000 3000 3000 3000
Does anyone know how to achieve this?
Thank you.
This achievable using dynamic query.
declare #cols nvarchar(max);
declare #sql nvarchar(1000);
with cte as (
select 12000 as col1, 12000/4 as col2
union all
select col1-col2, col2 from cte where col1 > col2
)
select #cols =
STUFF((select N',' + QUOTENAME(col2) from cte
FOR XML PATH('')
), 1, 1, '') + N'';
select #cols
You can avoid dynamic SQL if you know a maximum count:
Start with a mockup-table to simulate your issue
DECLARE #tbl TABLE(InitialValue DECIMAL(16,4));
INSERT INTO #tbl VALUES(12000),(20000),(10000);
--To test this I use a divisor of 4, try with other numbers
DECLARE #divisor DECIMAL(16,4)=4;
--This is the query
SELECT p.*
FROM
(
SELECT t.InitialValue / #divisor As DivResult
,t.InitialValue
,CONCAT('div',FORMAT(A.Nmbr,'00')) AS ColumnName
FROM #tbl t
CROSS APPLY(SELECT TOP(CAST(#divisor AS INT)) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM master..spt_values) A(Nmbr)
) t
PIVOT
(MAX(DivResult) FOR ColumnName IN(div01,div02,div03,div04,div05,div06,div07 /*add as many as you might need*/)) p;
The result
InitialValue div01 div02 div03 div04 div05 div06 div07
10000.0000 2500.000000000000000000000 2500.000000000000000000000 2500.000000000000000000000 2500.000000000000000000000 NULL NULL NULL
12000.0000 3000.000000000000000000000 3000.000000000000000000000 3000.000000000000000000000 3000.000000000000000000000 NULL NULL NULL
20000.0000 5000.000000000000000000000 5000.000000000000000000000 5000.000000000000000000000 5000.000000000000000000000 NULL NULL NULL
As you can see, the unused columns are returned but stay NULL.
I'd prefer this approach over dynamic sql as the consumer is better of in most cases if the result set and its structure is fixed and predictable...
Hint: You can add the divisor to your result set if needed...
It has to be dynamic query
Check below
Create TABLE Table1 (Origional int)
Declare #DivisonValue INT = 4
insert into Table1
VALUES (12000)
--Change the Top (12) to you what ever number you like. this will be your total number of columns
DECLARE #Columns VARCHAR(MAX) = (SELECT
',' + C.ColumnName + ' = Origional / ' + CAST(#DivisonValue AS VARCHAR(5))
/* Above line which you need to change for division */
FROM
(SELECT TOP (#DivisonValue)
ColumnId = ROW_NUMBER() OVER (ORDER BY s1.[object_id])
,ColumnName ='Result' + CONVERT(VARCHAR(10), ROW_NUMBER() OVER (ORDER BY s1.[object_id]))
FROM sys.all_objects AS s1 CROSS JOIN sys.all_objects AS s2
) AS C
ORDER BY
C.ColumnId
FOR XML PATH (''))
DECLARE #FullQuery VARCHAR(MAX) = 'SELECT Origional,'+ substring(#Columns,2,LEN(#Columns)-1) + ' FROM Table1'
EXEC (#FullQuery)
DROP TABLE table1
GO
Change the logic as per your need for division.
I have a table which has a column in which I am storing a comma separated text with single quotes for each of the comma separated values. These values are employee IDs. This is how it looks
Now, I have a SQL query wherein I need to put the value from this column into a SQL IN operator. Something like this:
select *
from EMPLOYEE_MASTER
where EMPLOYEEID IN (select CM_CONFIG_VALUE
from ADL_CONFIG_MAST_T
where CM_CONFIG_KEY like 'ATT_BIOMETRIC_OU_ID'
)
But this, does not work, the query when executed returns 0 rows whereas if I execute the query normally like below, it works.
select *
from EMPLOYEE_MASTER
where EMPLOYEEID IN('9F3DD4B791554DDE','C9B90D62851D43AB','828CB9E6204B4DDC')
Please suggest what I should do here. I have tried using substring to remove the first and the last character as well assuming that single quotes might be the issue, but that does not work either.
select * from EMPLOYEE_MASTER where EMPLOYEEID IN(select EMPLOYEEID from ADL_CONFIG_MAST_T where CM_CONFIG_KEY like 'ATT_BIOMETRIC_OU_ID')
column should be same in where COLUMNNAME IN (select COLUMNNMAE from tablename)
You can create a temp varible and then use exec command to get the desired result.
declare #temp varchar(200)
select #temp=CM_CONFIG_VALUE
from ADL_CONFIG_MAST_T
where CM_CONFIG_KEY like 'ATT_BIOMETRIC_OU_ID'
exec('select *
from EMPLOYEE_MASTER
where EMPLOYEEID IN (' + #temp + ')')
Try This:
DECLARE #ID VARCHAR(500);
DECLARE #Number VARCHAR(500);
DECLARE #comma CHAR;
SET #comma = ','
SET #ID = (select CM_CONFIG_VALUE
from ADL_CONFIG_MAST_T
where CM_CONFIG_KEY like %ATT_BIOMETRIC_OU_ID% + #comma);
Create table #temp (EMPLOYEEID varchar(500))
WHILE CHARINDEX(#comma, #ID) > 0
BEGIN
SET #Number = SUBSTRING(#ID, 0, CHARINDEX(#comma, #ID))
SET #ID = SUBSTRING(#ID, CHARINDEX(#comma, #ID) + 1, LEN(#ID))
Insert into #temp
select #Number
END
select *
from EMPLOYEE_MASTER
where EMPLOYEEID IN(select EMPLOYEEID from #temp)
The reason you are not getting it in your query is because your inner query returns only one row. So your query searches for '9F3DD4B791554DDE','C9B90D62851D43AB','828CB9E6204B4DDC' as as single record.
If your compatibility level is greater than or equal to 130 you can use STRING_SPLIT() function. Then your query would be
SELECT *
FROM EMPLOYEE_MASTER
WHERE EMPLOYEEID IN
(SELECT value AS empid
FROM ADL_CONFIG_MAST_T CROSS APPLY string_split(CM_CONFIG_VALUE, ',' )
WHERE CM_CONFIG_KEY LIKE 'ATT_BIOMETRIC_OU_ID' )
What this actually does is, it splits the CM_CONFIG_VALUE with ',' and returns them as rows. This is the value column I have referred. Then you use them with the IN clause.
Hope this helps!
Direct IN condition will not work here. You have split your string before searching. You can do that with XML options in SQL SERVER 2014
SELECT *
FROM EMP
WHERE EMPID IN (
SELECT a.c.value('.', 'VARCHAR(1000)')
FROM (
SELECT x = CAST('<a>' +
REPLACE(REPLACE(CM_CONFIG_VALUE , ',', '</a><a>'),'''','') + '</a>' AS XML )
FROM ADL_CONFIG_MAST_T
-- WHERE <your_condition>
) m
CROSS APPLY x.nodes('/a') a(c))
CHECK DEMO HERE
For the version 2016 and above you can use STRING_SPLIT with Compatibility level 130
Is there a way to access columns by their index within a stored procedure in SQL Server?
The purpose is to compute lots of columns. I was reading about cursors, but I do not know how to apply them.
Let me explain my problem:
I have a row like:
field_1 field_2 field_3 field_4 ...field_d Sfield_1 Sfield_2 Sfield_3...Sfield_n
1 2 3 4 d 10 20 30 n
I need to compute something like (field_1*field1) - (Sfield_1* Sfiled_1) / more...
So the result is stored in a table column d times.
So the result is a d column * d row table.
As the number of columns is variable, I was considering making dynamic SQL, getting the names of columns in a string and splitting the ones I need, but this approach makes the problem harder. I thought getting the column number by index could make life easier.
No, you can not use the ordinal (numeric) position in the SELECT clause.
Only in the ORDER BY clause can you use the ordinal position, because it's based on the column(s) specified in the SELECT clause.
First, as OMG Ponies stated, you cannot reference columns by their ordinal position. This is not an accident. The SQL specification is not built for dynamic schema either in DDL or DML.
Given that, I have to wonder why you have your data structured as you do. A sign of a mismatch between schema and the problem domain rears itself when you try to extract information. When queries are incredibly cumbersome to write, it is an indication that the schema does not properly model the domain for which it was designed.
However, be that as it may, given what you have told us, an alternate solution would be something like the following: (I'm assuming that field_1*field1 was meant to be field_1 * field_1 or field_1 squared or Power( field_1, 2 ) )
Select 1 As Sequence, field_1 As [Field], Sfield_1 As [SField], Sfiled_1 As [SFiled]
Union All Select 2, field_2, Sfield_2, Sfiled_2
...
Union All Select n, field_n, Sfield_n, Sfiled_n
Now your query looks like:
With Inputs As
(
Select 1 As Sequence, field_1 As [Field], Sfield_1 As [SField], Sfiled_1 As [SFiled]
Union All Select 2, field_2, Sfield_2, Sfiled_2
....
)
, Results As
(
Select Case
When Sequence = 1 Then Power( [Field], 2 ) - ( [SField] * [SFiled] )
Else 1 / Power( [Field], 2 ) - ( [SField] * [SFiled] )
End
As Result
From Inputs
)
Select Exp( Sum( Log( Result ) ) )
From Results
This might not be the most elegant or efficient but it works. I am using it to create a new table for faster mappings between data that I need to parse through all the columns / rows.
DECLARE #sqlCommand varchar(1000)
DECLARE #columnNames TABLE (colName varchar(64), colIndex int)
DECLARE #TableName varchar(64) = 'YOURTABLE' --Table Name
DECLARE #rowNumber int = 2 -- y axis
DECLARE #colNumber int = 24 -- x axis
DECLARE #myColumnToOrderBy varchar(64) = 'ID' --use primary key
--Store column names in a temp table
INSERT INTO #columnNames (colName, colIndex)
SELECT COL.name AS ColumnName, ROW_NUMBER() OVER (ORDER BY (SELECT 1))
FROM sys.tables AS TAB
INNER JOIN sys.columns AS COL ON COL.object_id = TAB.object_id
WHERE TAB.name = #TableName
ORDER BY COL.column_id;
DECLARE #colName varchar(64)
SELECT #colName = colName FROM #columnNames WHERE colIndex = #colNumber
--Create Dynamic Query to retrieve the x,y coordinates from table
SET #sqlCommand = 'SELECT ' + #colName + ' FROM (SELECT ' + #colName + ', ROW_NUMBER() OVER (ORDER BY ' + #myColumnToOrderBy+ ') AS RowNum FROM ' + #tableName + ') t2 WHERE RowNum = ' + CAST(#rowNumber AS varchar(5))
EXEC(#sqlCommand)
Say we have a table:
CREATE TABLE new_table
(
regionname character varying(10),
year integer,
month integer,
value integer
)
How to select for example the 3rd column "month" without using
SELECT month FROM new_table
but something like
SELECT "the 3rd column" FROM new_table
I want to first say that a table schema could change, so the column order could change, thus breaking any existing queries, stored procedures, or code outside your database. What exactly are you trying to accomplish? Do you just want to use numbers instead of names?
This answer:
Declare #WhichOne int;
Declare #Sql varchar(200);
Set #WhichOne = 2;
With cte As
(Select name, Row_Number() Over (Order By column_id) As rn
From sys.columns
Where Object_Name(object_id) = 'MyTable')
Select #Sql = 'Select ' + QuoteName(name) + ' From MyTable'
From cte
Where rn = #WhichOne;
Exec(#Sql);
Can be found here: http://www.codeproject.com/Questions/148495/Solved-SELECT-columns-by-column-index-NOT-by-colu
Is there a way to access columns by their index within a stored procedure in SQL Server?
The purpose is to compute lots of columns. I was reading about cursors, but I do not know how to apply them.
Let me explain my problem:
I have a row like:
field_1 field_2 field_3 field_4 ...field_d Sfield_1 Sfield_2 Sfield_3...Sfield_n
1 2 3 4 d 10 20 30 n
I need to compute something like (field_1*field1) - (Sfield_1* Sfiled_1) / more...
So the result is stored in a table column d times.
So the result is a d column * d row table.
As the number of columns is variable, I was considering making dynamic SQL, getting the names of columns in a string and splitting the ones I need, but this approach makes the problem harder. I thought getting the column number by index could make life easier.
No, you can not use the ordinal (numeric) position in the SELECT clause.
Only in the ORDER BY clause can you use the ordinal position, because it's based on the column(s) specified in the SELECT clause.
First, as OMG Ponies stated, you cannot reference columns by their ordinal position. This is not an accident. The SQL specification is not built for dynamic schema either in DDL or DML.
Given that, I have to wonder why you have your data structured as you do. A sign of a mismatch between schema and the problem domain rears itself when you try to extract information. When queries are incredibly cumbersome to write, it is an indication that the schema does not properly model the domain for which it was designed.
However, be that as it may, given what you have told us, an alternate solution would be something like the following: (I'm assuming that field_1*field1 was meant to be field_1 * field_1 or field_1 squared or Power( field_1, 2 ) )
Select 1 As Sequence, field_1 As [Field], Sfield_1 As [SField], Sfiled_1 As [SFiled]
Union All Select 2, field_2, Sfield_2, Sfiled_2
...
Union All Select n, field_n, Sfield_n, Sfiled_n
Now your query looks like:
With Inputs As
(
Select 1 As Sequence, field_1 As [Field], Sfield_1 As [SField], Sfiled_1 As [SFiled]
Union All Select 2, field_2, Sfield_2, Sfiled_2
....
)
, Results As
(
Select Case
When Sequence = 1 Then Power( [Field], 2 ) - ( [SField] * [SFiled] )
Else 1 / Power( [Field], 2 ) - ( [SField] * [SFiled] )
End
As Result
From Inputs
)
Select Exp( Sum( Log( Result ) ) )
From Results
This might not be the most elegant or efficient but it works. I am using it to create a new table for faster mappings between data that I need to parse through all the columns / rows.
DECLARE #sqlCommand varchar(1000)
DECLARE #columnNames TABLE (colName varchar(64), colIndex int)
DECLARE #TableName varchar(64) = 'YOURTABLE' --Table Name
DECLARE #rowNumber int = 2 -- y axis
DECLARE #colNumber int = 24 -- x axis
DECLARE #myColumnToOrderBy varchar(64) = 'ID' --use primary key
--Store column names in a temp table
INSERT INTO #columnNames (colName, colIndex)
SELECT COL.name AS ColumnName, ROW_NUMBER() OVER (ORDER BY (SELECT 1))
FROM sys.tables AS TAB
INNER JOIN sys.columns AS COL ON COL.object_id = TAB.object_id
WHERE TAB.name = #TableName
ORDER BY COL.column_id;
DECLARE #colName varchar(64)
SELECT #colName = colName FROM #columnNames WHERE colIndex = #colNumber
--Create Dynamic Query to retrieve the x,y coordinates from table
SET #sqlCommand = 'SELECT ' + #colName + ' FROM (SELECT ' + #colName + ', ROW_NUMBER() OVER (ORDER BY ' + #myColumnToOrderBy+ ') AS RowNum FROM ' + #tableName + ') t2 WHERE RowNum = ' + CAST(#rowNumber AS varchar(5))
EXEC(#sqlCommand)