I have already googled for this
I have a Table with following structure in SQL 2000
ID ContactName Designation
1 A CEO
2 B ABC
3 C DEF
4 D GHI
I need the Output as follows
ContactName1 Contactname2 ContactName3 ContactName4
A CEO B ABC C DEF D GHI
Any Suggestions ?
It occurs to me that a lot of the examples are for cross tab queries involving aggregation, which yours does not appear to need. While I do not necessarily condone Dynamic SQL, the below should give you the results you want.
Create table #Contacts (id int)
Declare #ContactTypes int
Declare #CAD varchar(100)
Declare #I int
Declare #sql nvarchar(4000)
Set #i = 1
Select #ContactTypes =
Sum(sub.Types)
from ( Select Count(1) as Types from contacts
group by ContactName, Designation) as sub
Print #ContactTypes
While #i <= #ContactTypes
Begin
set #sql = 'alter table #Contacts Add ContactName' +
Cast(#I as varchar(10)) + ' varchar(100)'
exec sp_executesql #sql
Set #I = #i + 1
End
Insert into #Contacts (id) values (1)
Set #i = 1
Declare crsPivot cursor
for Select ContactName + ' ' + Designation
from contacts
open crsPivot
Fetch next from crsPivot into #CAD
While (##Fetch_Status = 0)
Begin
Set #sql = 'Update #Contacts set ContactName'
+ Cast(#I as varchar(10)) +' = ' + quotename(#CAD,'''')
exec sp_executesql #sql
Set #i = #i + 1
Fetch next from crsPivot into #CAD
End
close crsPivot
Deallocate crsPivot
select * From #Contacts
You need to use a PIVOTED Table
This should work with 2000 also - wg. without PIVOT
http://www.sqlteam.com/item.asp?ItemID=2955
Yet another SQL Cross Tab proc http://johnmacintyre.ca/codespct.asp
Related
I have this table:
ID
Name
Role
1
Tom
Admin
2
Tom
User
3
John
Admin
From this table I need to copy the data into the two tables like this:
User:
ID
Name
1
Tom
2
John
UserRole:
UserID
RoleID
1
Admin
1
User
2
Admin
How can I do it in a stored procedure?
You can use queries:
insert into user (name)
select distinct name
from following;
insert into userrole (userid, roleid)
select u.userid, f.roleid
from following f join
user u
on f.name = u.name;
These can be incorporated into a stored procedure.
you can also try merge add,update, delete. Merge uses the composite index or primary key to find matching rows. This is a data warehouse way of etl. you may have to set identity off for a primary key.
use MyDataDB
declare #Output as varchar(max)
declare #ColumnName as varchar(100)
declare #TableName as varchar(30)='your_table_name'
declare #UpdateStatement as varchar(max)=''
declare #InsertStatement as varchar(max)=''
declare #InsertStatement2 as varchar(max)=''
declare #DeleteStatement as varchar(max)=''
Declare #Join as varchar(max)
declare #JoinColumns Table(ColumnName varchar(50))
---- Add your primary Key here or composite index
Insert into #JoinColumns(ColumnName)
values('YourKeyID')
select #Join=
(select ' AND TARGET.'+ColumnName+'=SOURCE.'+ColumnName from #JoinColumns for xml path(''))
select #Join=right(#Join,len(#Join)-5)
declare c1 cursor
for
SELECT
COLUMN_NAME
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME = #TableName
open c1
fetch next from c1 into #ColumnName
set #Output=N'MERGE ReportData.dbo.'+ #TableName + ' as TARGET USING ReportData.dbo.' + #TableName + '_Stage as SOURCE ON
(' + #Join +') WHEN MATCHED THEN ';
set #UpdateStatement=N' UPDATE SET ';
set #InsertStatement =N' WHEN NOT MATCHED BY TARGET THEN INSERT(';
set #InsertStatement2=N' Values(';
set #DeleteStatement=N' WHEN NOT MATCHED BY SOURCE THEN DELETE';
while ##FETCH_STATUS=0
begin
if not exists(select '' from #JoinColumns where ColumnName=#ColumnName)
begin
if #UpdateStatement=N' UPDATE SET '
SET #UpdateStatement=#UpdateStatement + 'TARGET.' + #ColumnName+'='+'SOURCE.'+#ColumnName
else
SET #UpdateStatement=#UpdateStatement + ',TARGET.' + #ColumnName+'='+'SOURCE.'+#ColumnName
end
if #InsertStatement =N' WHEN NOT MATCHED BY TARGET THEN INSERT('
BEGIN
Set #InsertStatement=#InsertStatement+#ColumnName
Set #InsertStatement2=#InsertStatement2+'SOURCE.'+#ColumnName
END
ELSE
BEGIN
Set #InsertStatement=#InsertStatement+','+#ColumnName
Set #InsertStatement2=#InsertStatement2+',SOURCE.'+#ColumnName
END
fetch next from c1 into #ColumnName
end
close c1
deallocate c1
SET #Output=#Output + #UpdateStatement
SET #Output=#Output + #InsertStatement+') '
SET #Output=#Output + #InsertStatement2+') '
SET #Output=#Output + #DeleteStatement+';'
select #Output
I have a following table:
Table 1
And I want to show only columns that have at least one value under 50:
Table 2
I need a stored procedure that does this. The trick is that I want to use it on multiple tables but the number of columns can vary from table to table.
Can this be done?
Wish this will have some help.
SET NOCOUNT ON
DECLARE
#tablename VARCHAR(50) = 'Table1',
#valuetocompare INT = 50,
#otherfields VARCHAR(100) = 'Date, Hour,';
DECLARE #t AS TABLE (cname VARCHAR(10), cvalue INT)
DECLARE #sql NVARCHAR(1000);
DECLARE #cname VARCHAR(128);
DECLARE c CURSOR
FOR
SELECT NAME
FROM sys.[columns] AS c
WHERE c.[object_id] = OBJECT_ID(#tablename)
;
OPEN c;
FETCH NEXT FROM c INTO #cname;
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = 'select ''' + #cname + ''', ' + #cname + ' from ' + #tablename;
INSERT INTO #t
(
cname,
cvalue
)
EXECUTE (#sql);
FETCH NEXT FROM c INTO #cname;
END
CLOSE c;
DEALLOCATE c;
DECLARE #cnames VARCHAR(100) = '';
WITH dcnames AS (
SELECT DISTINCT cname
FROM #t
WHERE cvalue < #valuetocompare
)
SELECT #cnames = #cnames + cname + ','
FROM dcnames;
IF #cnames = ''
PRINT 'No column value is less than ' + CAST(#valuetocompare AS VARCHAR);
ELSE
BEGIN
SET #sql = 'select ' + #otherfields + LEFT(#cnames, LEN(#cnames) - 1) + ' from ' + #tablename;
EXECUTE (#sql);
END
I have the following code which works fine for one table but I am trying to figure out how to make it loop.
DECLARE #sql NVARCHAR(2000)
DECLARE #table VARCHAR(100)
DECLARE #command NVARCHAR(1000)
SELECT #table = ( VV.SRC_CD )
FROM VV
SET #sql = 'SELECT [CD],[SRC_CD],[SRC_CD_DESC],[DSC],[REFRESH_DT],[GEN_DSC] = CAST(null as VARCHAR(50)) INTO dbo.vv_' + #table
+
' FROM [vv] A WHERE A.SRC_CD <> ''GEN'' AND A.DSC <> ''NO DATA'' AND A.DSC <> ''(BLANK) NO'' AND A.src_cd = '''
+ #table + ''''
EXEC Sp_executesql
#stmt = #sql
The code that populates the #table variable returns one row. What I am trying to do is get this procedure to loop one time for each distinct value in the table for that row. The distinct clause doesn't work here and I have tried a basic table array with no luck.
Do I need to modify this to use a cursor?
It sounds like you're in need of a cursor, something like:
DECLARE #Iterator NVARCHAR(100)
,#sql NVARCHAR(MAX)
DECLARE xyz CURSOR
FOR
--Select stuff to iterate over
SELECT DISTINCT SRC_CD
FROM w
OPEN xyz
FETCH NEXT FROM xyz
INTO #Iterator
WHILE ##FETCH_STATUS = 0
BEGIN
--Do stuff
SET #sql = 'SELECT [CD],[SRC_CD],[SRC_CD_DESC],[DSC],[REFRESH_DT],[GEN_DSC] = CAST(null as VARCHAR(50))
INTO dbo.vv_' + #Iterator +'
FROM [vv] A
WHERE A.SRC_CD <> ''GEN''
AND A.DSC <> ''NO DATA''
AND A.DSC <> ''(BLANK) NO''
AND A.src_cd = ''' + #Iterator + ''''
PRINT (#sql)
FETCH NEXT FROM xyz
INTO #Iterator
END
CLOSE xyz
DEALLOCATE xyz
GO
I left PRINT in there so you can ensure the output is as desired before executing.
My table is a dynamic one. E.g.:
id SUBJECT
1 his
2 math
3 sci
4 opt
5 ENG
6 SOC
The number of rows is not limited. There could be a hundred. I want output like this:
ID 1 2 3 4 5 6
HIS MATH SCI OPT ENG SOC
I could use a pivot query, but I would have to know the number of columns. How can I do this without knowing the number of columns in advance?
i got an answer but it's very tricky
create a table for all your records
count the records
create a table with that much number of columns
create a comma separated variable for the table which has records
then split the comma separated variables into multiple columns
here is the code
DECLARE #HEADDESC NVARCHAR(150)
DROP TABLE #HEADS
CREATE TABLE #HEADS
(
ID INT IDENTITY
,HEADS NVARCHAR(150)
,NU INT
)
DECLARE #NO INT;
SET #NO = 0
DECLARE C1 CURSOR FOR (
SELECT HEADDESC
FROM GMC.FEEHEAD_MASTER
WHERE CODE = 'GF' AND HEADDESC <> '')
OPEN C1
FETCH NEXT FROM C1 INTO #HEADDESC
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #HEADDESC
SET #NO = #NO+1
INSERT INTO #HEADS(HEADS,NU)
VALUES(#HEADDESC,#NO)
FETCH NEXT FROM C1 INTO #HEADDESC
END
--SELECT * FROM #HEADS
CLOSE C1
DEALLOCATE C1
DECLARE #COLNO INT
SET #COLNO = (SELECT COUNT(*) FROM #HEADS)
DECLARE #COLUMNS VARCHAR(8000)
SELECT #COLUMNS = COALESCE(#COLUMNS +','+ CAST(HEADS AS VARCHAR) ,
CAST(HEADS AS VARCHAR))
FROM #HEADS
--GROUP BY HEADS
DECLARE #value NVARCHAR(100)
SET #value = ',1,STUDENTIDNO,STUDENTNAME,'
SET #COLUMNS = #VALUE+#COLUMNS
SET #COLNO = #COLNO+4
--SELECT #COLUMNS
DROP TABLE #HEADSCOMMA
CREATE TABLE #HEADSCOMMA(HEADS NVARCHAR(3000))
INSERT INTO #HEADSCOMMA VALUES (#COLUMNS)
DROP TABLE #TEMP
CREATE TABLE #TEMP(COL1 NVARCHAR(1000))
DECLARE #SQL NVARCHAR(MAX)
DECLARE #COL NVARCHAR(1000)
DECLARE #COL1 INT
DECLARE #COLNAME NVARCHAR(1000)
SET #COL1 = 2
SET #COL = 'COL'
PRINT #COL1
--SET #COLNAME = #COL +CAST(#COL1 AS NVARCHAR(10))
WHILE #COL1 < =#COLNO
BEGIN
SET #COLNAME = #COL +CAST(#COL1 AS NVARCHAR(100))
PRINT #COLNAME
SET #SQL = 'ALTER TABLE #TEMP ADD '+#COLNAME+' NVARCHAR(100)'
EXEC(#SQL)
SET #COL1= #COL1+1
END
--SELECT * FROM #HEADSCOMMA -- COMMA SEPERATED VALUES
DECLARE #S VARCHAR(8000), #DATA VARCHAR(8000)
--DROP TABLE #NORMALISEDTABLE
--CREATE TABLE #NORMALISEDTABLE (HEADS NVARCHAR(200))
SELECT #S=''
WHILE EXISTS (SELECT * FROM #HEADSCOMMA WHERE HEADS>#S)
BEGIN
SELECT #S=HEADS FROM #HEADSCOMMA WHERE HEADS>#S
PRINT #S
SELECT #DATA=''''+REPLACE(#S,',',''',''')+''''
PRINT #DATA
INSERT INTO #TEMP
EXEC('SELECT '+#DATA)
END
SELECT * FROM #temp
will give the records
Dynamic SQL is an option.
It is possible to write a generic function/procedure/select/somethingElse to cross-join a table against himself 'n' times? (yes, 'n' is a given parameter : )
How would you do it?
Example
Having this table:
Value
-------
1
2
3
cross join it 2 times, would return:
Value | Value
------------------
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
Using dynamic SQL, SQL Server 2005+ (#table_name and #numCrossJoins are stored procedure parameters):
DECLARE #upperLimit INT
SET #upperLimit = 1
DECLARE #SQL NVARCHAR(MAX)
SET #SQL = 'SELECT * FROM '+ #table_name +' '
BEGIN
WHILE (upperLimit <= #numCrossJoins)
BEGIN
SET #SQL = #SQL + 'CROSS JOIN '+ QUOTENAME(#table_name) +' '
SET #upperLimit = #upperLimit + 1
END
EXEC sp_executesql #SQL
END
You can generate dynamic sql to output as many cross joins as you need:
create table #t (value int)
insert into #t values (1)
insert into #t values (2)
insert into #t values (3)
declare #n int
set #n = 4
declare #sql varchar(max)
set #sql = 'SELECT * FROM #t t'
declare #i int
set #i = 0
while (#i <= #n)
begin
set #sql = #sql + ' cross join #t t' + CAST(#i as varchar)
set #i = #i + 1
end
print #sql
execute(#sql)
drop table #t
Try this:
SET #SQL = 'SELECT * FROM ' + replicate('[' + #table_name + '],', #N);
set #SQL = LEFT(LEN(#SQL) - 1);
EXEC sp_executesql #SQL;
If you need to come up with all possible permutations, here is an example:
All Permutations For A String