Using Row_number() OVER(partition BY..) along with declaring local variables - sql-server

I have a sql query, in this sql query I want to select distinct columns irrespective of column first. For other sql query I use Row_number() OVER(partition BY..) and I also need to use inner join. The query in which I want to use row_number and inner join is -
DECLARE #columns NVARCHAR(MAX)
DECLARE #params NVARCHAR(MAX) = '#columns NVARCHAR(MAX) OUTPUT'
DECLARE #sql NVARCHAR(MAX) = 'SELECT #columns = STUFF(
(
SELECT '',''+ [column_name] FROM information_schema.columns
WHERE (table_schema = ''dbo''
AND table_name = ''main_mps_dqs_analog'')
AND (ordinal_position <= 73) FOR XML PATH('''')),1,1,'''')'
EXEC sp_executesql #sql, #params, #columns OUTPUT
SET #sql = 'SELECT '+ #columns + ' FROM dbo.main_mps_dqs_analog WHERE logtime BETWEEN ''2014-10-10 07:17:00'' AND ''2014-10-10 08:47:00'''
EXEC(#sql)
I want to apply inner join of this table with INDUS2_BDS.dbo.ddtable and I want beam_current and logtime of this INDUS2 database table and how to apply partition BY beam_current in this query.

SET #sql = 'SELECT ' + #columns + ' ,AnotherTable.beam_current, RowNumber() Over(Partition By SomeColumn Order By SomeColumn) AS Rn
FROM dbo.TableName join AnotherTable on TableName.SomeColumn = AnotherTable.SomeColumn
WHERE logtime BETWEEN ''2014-10-10 07:17:00'' AND ''2014-10-10 08:47:00'''
I solved it by this sql query with the help from Giorgi

Related

Rows to Columns RDLC

i have data in below format. this data is coming through SQL Query.
i want to show it in below format either by query or by rdlc report.
You need to use dynamic SQL to make it.
From your expected result you can try to follow thoes step to make it.
use row_number function make row number by Name, because we need to join base on that row_number.
get the use MAX and MIN to make row number calendar table. from 1 to max(rn). the table can let use outer join
declare a var #tables to make the OUTER JOIN execute SQL (each LEFT JOIN maen a group of Crew#).
declare a var #col to make column, which you want to select (Employee) from each table.
then use execute dynamic execute it.
look like this.
create table T
(
Name varchar(50),
Employee VARCHAR(50)
)
insert into T values ('Crew#1','TR123');
insert into T values ('Crew#1','311');
insert into T values ('Crew#2','DDD');
insert into T values ('Crew#2','12121');
insert into T values ('Crew#1','SDDAS');
insert into T values ('Crew#3','31114312');
insert into T values ('Crew#3','DD14124D');
insert into T values ('Crew#3','1214124121');
insert into T values ('Crew#3','SDD412AS');
DECLARE #tables AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX),
#col AS NVARCHAR(MAX);
SET #tables = STUFF((SELECT distinct ' LEFT JOIN ' + ' (SELECT * FROM CTE WHERE Name = '''+Name+''') '+QUOTENAME(Name)+' on t1.smallRN = '+QUOTENAME(Name)+'.rn'
FROM T
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #col = STUFF((SELECT distinct ', ' + QUOTENAME(Name)+'.Employee as '''+ QUOTENAME(Name) +''''
FROM T
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #col = substring(#col,1, len(#col))
set #query = '
WITH CTE AS (
SELECT *,ROW_NUMBER() OVER(PARTITION BY Name ORDER BY Name) rn
FROM T
),CTE1 AS(
SELECT MIN(rn) smallRN,MAX(rn) bigRN
FROM CTE
UNION ALL
SELECT smallRN+1,bigRN
FROM CTE1
WHERE smallRN < bigRN
)
SELECT '+#col+'
FROM CTE1 t1 ' + #tables
execute(#query)
sqlfiddle
Creatin tbale
First we will create a temp table where we will stock the data that you have and your table
create table #table1
(
[Crew Name] varchar(500) ,
Employee varchar(500)
)
INsert into #table1
values (....)
select * from #table1
Dynamic selection
then we will create a dynamic query to get the columns that we have, that way we can add as much crews as we want,
declare #DynamicPivotQuery as nvarchar(max)
declare #ColumnName as nvarchar(max)
select #ColumnName = ISNULL(#ColumnName +',','') + QUOTENAME([Crew Name])
from (select distinct [Crew Name] from #table1) as Country
set #DynamicPivotQuery = N'select ' +#ColumnName + '
from #table1
Pivot ( MAX(Employee)
FOR [Crew Name] in (' +#ColumnName+')) as Pivoted
'
exec (#DynamicPivotQuery)
this way we will get only the first row for every column
so we have to find a way to aggregate and get the other columns as well just to demonstrate i will union the Mmin also this is where i stoped my testes but you can do more then this with some testes
now the union :
declare #DynamicPivotQuery as nvarchar(max)
declare #ColumnName as nvarchar(max)
select #ColumnName = ISNULL(#ColumnName +',','') + QUOTENAME([Crew Name])
from (select distinct [Crew Name] from #table1) as Country
set #DynamicPivotQuery = N'select ' +#ColumnName + '
from #table1
Pivot ( MAX(Employee)
FOR [Crew Name] in (' +#ColumnName+')) as Pivoted
union
select ' +#ColumnName + '
from #table1
Pivot ( MIN(Employee)
FOR [Crew Name] in (' +#ColumnName+')) as Pivoted
'
exec (#DynamicPivotQuery)
here is the result :
if you follow this way i'm sure that you will find a way to union all the result
You can add this result into a temp table
then add a column which will be a reference into this temp table
then use pivot function
To know more about pivot Visit :
https://msdn.microsoft.com/en-us/azure/data-lake-analytics/u-sql/pivot-and-unpivot-u-sql
you can use also SSIS to a very handy tool and easy to use
Using dynamic PIVOT if you dont have a set Crew columns.
DECLARE #ColumnString VARCHAR(256)
DECLARE #ColumnHeadrer VARCHAR(256)
DECLARE #sql varchar(1000)
CREATE TABLE #ColumnValue
(
Value VARCHAR(500),
ColumnHeader VARCHAR(256)
)
INSERT INTO #ColumnValue (Value, ColumnHeader)
SELECT DISTINCT '[' + CrewName + ']',
'ISNULL(' + CrewName + ','''') AS ' + CrewName
FROM CrewTable
SELECT #ColumnString = COALESCE(#ColumnString + ',', '') + Value,
#ColumnHeadrer = COALESCE(#ColumnHeadrer + ',', '') + ColumnHeader
FROM #ColumnValue
SET #sql =
'
SELECT ' + #ColumnHeadrer + '
FROM
(
SELECT Employee,
CrewName,
ROW_NUMBER() OVER(PARTITION BY CrewName ORDER BY CrewName) AS rnk
FROM CrewTable
) AS P
PIVOT
(
MAX(Employee) FOR [CrewName] IN ('+#ColumnString+')
) AS pv
'
EXEC (#sql)

Dynamic Pivot SQL in the Common Table Expression (CTE)

I am trying to Pivot a result of a CTE. Due to the privacy laws i cannot put my query and resultset here but the example looks like the below:
WITH CTE1
AS ( select ....)
,CTE2
AS (Select...)
,CTE3
as (Select...)
Below is the result of my CTE2:
and i want the result as
The main issue i am having here is to pivot the resultset with multiple and dynamic Pivot columns between CTE2 and CTE3 as i need to use the Pivot data in CTE3. Is there any solution without changing the CTE's to TempTable? Any help will be appreciated.
I think it's going to be something like this.
Dynamic Pivot:
DECLARE #query VARCHAR(4000)
DECLARE #years VARCHAR(2000)
SELECT #years = STUFF(( SELECT DISTINCT'],[' + [factor_label]
FROM [TEMP_lacp_factors]
ORDER BY '],[' + [factor_label]
FOR XML PATH('')
), 1, 2, '') + ']'
SET #query =
'SELECT * FROM
(
SELECT [date_],[issue_id],[cusip],[Factor_value],[factor_label]
FROM [TEMP_lacp_factors]
)t
PIVOT (MAX([factor_value]) FOR [factor_label]
IN ('+#years+')) AS pvt'
EXECUTE (#query)
Dynamic Pivot and Select Into:
-- Drop the table; you create it dynamically
Drop Table tempTable
--Start creating all objects for Dyanmic Pivot
DECLARE #query VARCHAR(4000)
DECLARE #years VARCHAR(2000)
SELECT #years = STUFF(( SELECT DISTINCT'],[' + [factor_label]
FROM [TEMP_lacp_factors]
ORDER BY '],[' + [factor_label]
FOR XML PATH('')
), 1, 2, '') + ']'
SET #query =
-- Objects that are created above, are put into the table you are about to create below
'SELECT * INTO tempTable FROM (SELECT * FROM
(
SELECT [date_],[issue_id],[cusip],[Factor_value],[factor_label]
FROM [TEMP_lacp_factors]
)t
PIVOT (MAX([factor_value]) FOR [factor_label]
IN ('+#years+')) AS pvt) X'
EXECUTE (#query)
-- Select everything from the dynamically created table ('tempTable') to see results
Select * from tempTable
I'm not 100% sure what you are doing, so it's just a best guess.

How to SELECT * and get all field alphabetical ordered

This could be a strange question.
I have a table with 100+ columns. I would like to SELECT * all columns and get the resulting query with columns ordered alphabetically.
Is it possible in T-SQL?
Thanks
You could build a dynamic SQL statement using the information available in the system catalog view.
The sample code below shows how:
DECLARE #sql AS NVARCHAR(MAX)
DECLARE #cols AS NVARCHAR(MAX)
DECLARE #tbl NVARCHAR(MAX) = N'your_table' -- this is your source table
SELECT #cols= ISNULL(#cols + ',','') + QUOTENAME(c.name)
FROM sys.tables t
join sys.columns c ON c.object_id = t.object_id
WHERE t.name = #tbl
ORDER BY c.name
SET #sql = N'SELECT ' + #cols + ' FROM ' + #tbl
EXEC sp_executesql #sql
DynamicSQL (SQL Server) example:
declare #TABLE varchar(200) set #TABLE='persons'
declare #SQL nvarchar(max)
set #SQL='select '
select #SQL= #SQL + column_name + ','
from information_schema.columns where table_name=#TABLE order by column_name
select #SQL = left(#SQL,len(#SQL)-1) + ' from ' + #TABLE -- trims the trailing comma
--select #SQL -- If you want to see the query
exec sp_executesql #SQL
DECLARE #Table NVARCHAR(MAX)='T'--pass your table name
DECLARE #SQL NVARCHAR(MAX)='SELECT '
SELECT #SQL=#SQL+',' +NAME FROM
(
SELECT TOP 100 QUOTENAME(NAME) AS NAME
FROM sys.columns
WHERE object_id =
(
SELECT OBJECT_ID FROM sys.tables
WHERE NAME =#Table
)
ORDER BY NAME
) AS SS
SELECT #SQL=STUFF(#SQL,8,1,'')+' FROM '+#Table
EXEC sp_executesql #sql

What is the T-SQL syntax to exclude a duplicate column in the output when joining 2 tables?

I am using SQL Server 2014 and I have the following T-SQL query which joins 2 tables:
SELECT a.*, b.* FROM TEMP a
INNER JOIN Extras b ON b.ResaID = a.ResaID
I would like to pull ALL the columns from TEMP and all the columns from "Extras" with the exception of the ResaID column as it is already included in a.* in the above query. Basically, I want to pull a.* + b.* (excluding b.ResaID).
I know I can write the query in the form:
Select a.*, b.column2, b.column3,...
but since b.* has got around 40 columns, is there a way to write the query in a more simplified way to exclude b.ResaID, rather than specify each of the columns in the "Extras" table?
Unfortunately, there is no such syntax. You could either use asterisks (*) and just ignore the duplicated column in your code, or explicitly list the columns you need.
You should create a view and select the columns you need from that view. Here is a script that will generate that view for you:
DECLARE #table1 nvarchar(20) = 'temp'
DECLARE #table1key nvarchar(20) = 'ResaID'
DECLARE #table2 nvarchar(20) = 'Extras'
DECLARE #table2key nvarchar(20) = 'ResaID'
DECLARE #viewname varchar(20) = 'v_myview'
DECLARE #sql varchar(max) = ''
SELECT #sql += '], a.[' + column_name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = #table1
SELECT #sql += '], b.[' + column_name
FROM
(
SELECT column_name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = #table2
EXCEPT
SELECT column_name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = #table1
) x
SELECT
#sql = 'CREATE view ' +#viewname+ ' as SELECT '
+ STUFF(#sql, 1, 3, '') + '] FROM ['
+#table1+ '] a JOIN ['+ #table2
+'] b ON ' + 'a.' + #table1key + '=b.' + #table2key
EXEC(#sql)
You can simply solve this using a dynamic sql query.
DECLARE #V_SQL AS NVARCHAR(2000)='' --variable to store dynamic query
,#V_TAB1 AS NVARCHAR(200)='TEMP' --First Table
,#V_TAB2 AS NVARCHAR(200)='Extras' --Second Table
,#V_CONDITION AS NVARCHAR(2000)='A.ResaID = B.ResaID' --Conditions
SELECT #V_SQL = STUFF(
( SELECT ', '+TCOL_NAME
FROM
( SELECT 'A.'+S.NAME AS TCOL_NAME
FROM SYSCOLUMNS AS S
WHERE OBJECT_NAME(ID) = #V_TAB1
UNION ALL
SELECT 'B.'+S.NAME
FROM SYSCOLUMNS AS S
WHERE OBJECT_NAME(ID) = #V_TAB2
AND S.NAME NOT IN (SELECT S.NAME
FROM SYSCOLUMNS AS S
WHERE OBJECT_NAME(ID) = #V_TAB1)
) D
FOR XML PATH('')
),1,2,'')
EXECUTE ('SELECT '+#V_SQL+'
FROM '+#V_TAB1+' AS A
INNER JOIN '+#V_TAB2+' AS B ON '+#V_CONDITION+' ')

SQL Server dynamic pivot as stored procedure using parameters

I have been working to make a dynamic pivot in SQL Server that a user could call in a stored procedure and pass specified parameters ie:
exec piv(schema, table, agg_type, aggCol, newCol)
I am struggling to finish out the schema and table parameters.
Here is what I have so far:
BEGIN
DECLARE #Piv AS NVARCHAR(max) --final pivot. print this to see the exec statement
DECLARE #NewColumns AS NVARCHAR(max) -- extract data and format to make new columns
DECLARE #COLUMNS AS NVARCHAR(MAX) -- list of all columns to be used for CTE below
DECLARE #PivColumns AS NVARCHAR(MAX) --list of all columns except the 2 columns involved in pivot
--declaring parameters here for now
declare #aggCol nvarchar(max)
declare #newCol nvarchar(max)
declare #table nvarchar(max)
declare #schm nvarchar(max)
--To be used for parameters in the SP
set #schm = 'dbo'
set #table = 'Report'
set #aggCol = 'Flag'
set #newCol = 'Category'
-- extracts data and formats for new columns... here is where I'm stuck.
-- I have tried every way I can find to pass the variables in this statement and no luck
SELECT #NewColumns = COALESCE(#NewColumns + ',','') + QUOTENAME(CATEGORY) + char(13)
FROM
(
SELECT DISTINCT Category --needs to be dynamic ie: #newCol
FROM
dbo.Report --needs to be dynamic ie: #table
) AS B
-- list of all columns to be used for CTE below
SELECT #Columns = COALESCE(#Columns + ',','') + QUOTENAME(COLUMN_NAME) + char(13)
FROM
(
SELECT DISTINCT COLUMN_NAME
FROM
(
SELECT
SCHEMA_NAME(T.SCHEMA_ID) AS 'SCHEMA_NAME' -- GET THIS WORKING TO GET A SPECIFIC TABLE
,T.NAME AS 'TABLE_NAME'
,C.NAME AS 'COLUMN_NAME'
FROM SYS.COLUMNS C
INNER JOIN SYS.TABLES T ON C.OBJECT_ID = T.OBJECT_ID
WHERE T.NAME = #table) AS A
) AS B
ORDER BY B.COLUMN_NAME
--list of all columns except the 2 columns involved in pivot
SELECT #PivColumns =
COALESCE(#PivColumns + ',','') + QUOTENAME(COLUMN_NAME) + char(13)
FROM
(
SELECT DISTINCT COLUMN_NAME
FROM
(
SELECT
SCHEMA_NAME(T.SCHEMA_ID) AS 'SCHEMA_NAME' -- GET THIS WORKING TO GET A SPECIFIC TABLE
,T.NAME AS 'TABLE_NAME'
,C.NAME AS 'COLUMN_NAME'
FROM SYS.COLUMNS C
INNER JOIN SYS.TABLES T ON C.OBJECT_ID = T.OBJECT_ID
WHERE T.NAME = #table
and (C.name not like #aggCol or C.name not like #newCol)
) AS A
) AS B
ORDER BY B.COLUMN_NAME
--Removes columns that are used on the pivot
SET #PivColumns = REPLACE(REPLACE(#PivColumns,char(13)+',['+#aggcol+']',''),char(13)+',['+#newcol+']','')
--final statement to print/exec
SET #Piv ='
WITH T1 AS
(
SELECT
'+#COLUMNS+'
FROM
'+#table+'
)
SELECT
'+#PivColumns+'
,'+#NewColumns+'
FROM T1
PIVOT
(MAX(FLAG) FOR CATEGORY IN ('+#NewColumns+'))AS PIV'
print(#Piv)
END
Feel free to add suggestions or edit in any way ie: tempTable, cte, etc...
I built this in another window that gets me what I need but I do not think I can use it in the first statement:
BEGIN
DECLARE #NewColumns AS NVARCHAR(max)
declare #newCol nvarchar(max)
declare #table nvarchar(max)
set #newCol = 'Category'
set #table = '[dbo].[REPORT]'
Select #NewColumns =
'
DECLARE #NewColumns AS NVARCHAR(max)
declare #table nvarchar(max)
SELECT #NewColumns = COALESCE(#NewColumns + '','','''') + QUOTENAME(CATEGORY) + char(13)
FROM
(
SELECT DISTINCT '+#newCol+'
FROM
'+#table+'
) AS B
print(#NewColumns)
'
exec(#NewColumns)
end
Try this
DECLARE #SQL VARCHAR(MAX)
DECLARE #List VARCHAR(MAX)
DECLARE #SQLList nVARCHAR(MAX)
SET #SQLList=N'select #List=stuff((SELECT DISTINCT '',''+AccountType FROM '+#table+'. FOR XML PATH('''')),1,1,'''')'
exec sp_executesql #SQLList ,N'#List VARCHAR(MAX) out', #List out
select #List
SET #SQL=
'
SELECT * FROM (SELECT '+#newCol +','+#aggCol+'
FROM '+#table+') AS SourceTable
PIVOT
(
'+#agg_type+'('+#aggCol+')
FOR '+#newCol +'IN ('+#List+')
) AS PivotTable;'
exec(#SQL)

Resources