Cross Join 'n' times a table - sql

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

Related

concatenate String with Int in column

I need to dynamically loop through column names and fetch the records.
Below is my table, and I am using SQL Server 2017.
-- DECLARE #cnt INT = 1;
-- WHILE #cnt < 3
-- BEGIN
-- SELECT 'Name' + #cnt FROM Emp
-- SET #cnt = #cnt + 1;
-- END;
--GO
but this query is not working.
How to loop through columns such as Name+#cnt?
Expected output:
User1
User2
User3
Emp table:
DECLARE #statement NVARCHAR(MAX) = '', #cnt INT = 1;
WHILE #cnt < 4
BEGIN
SET #statement = #statement + ' select Name' + CAST(#cnt AS VARCHAR) + ' from Emp;'
SET #cnt = #cnt + 1;
END
EXECUTE sp_executesql #statement
Dynamic SQL would be best fit for this task:
declare #sql varchar(1000) = '';
select #sql = #sql + ' select ' + name + ' from MYDATABASE.dbo.Emp ' from MYDATABASE.sys.columns
where name like 'Name[1-3]'
exec(#sql)
The query will search for column names like Name1, Name2, Name3 and construct three SELECT queries, which then will be executed by EXEC function.
NOTE: I assumed that table is in dbo schema and you need to use your database instead of MYDATABASE.

SQL Server : get column name of a table using condition

I have a sample table here - I want to get all the columns that have the value of 1 only. Is it possible?
Its absolutely possible but the process is lengthy, I am using loop to check each column's
data exists by retrieving column name from sys.columns. Please try this if it helps you in any term:
Here I am checking each column for value 1 only
CREATE TABLE testing(val1 INT, val2 INT, val3 INT)
INSERT INTO testing VALUES
(1, 0, 1),(1, 0, 1),(1, 1, 1)
Table: testing
val1 val2 val3
1 0 1
1 0 1
1 1 1
DECLARE #sql NVARCHAR(500), #list VARCHAR(500)
DECLARE #num INT=1, #col_name VARCHAR(100) = NULL, #cnt INT
WHILE(#num<=3)
BEGIN
SELECT #col_name = name FROM sys.columns
WHERE object_id = OBJECT_ID('testing') and column_id = #num
SET #cnt = 0
SET #sql = '
IF NOT EXISTS(SELECT 1 FROM testing WHERE ' + #col_name + ' = 0) SET #cnt = 1'
EXEC sp_executesql #sql, N'#cnt INT OUT', #cnt OUT
IF #cnt = 1
SET #list = COALESCE(#list + ',', '') + #col_name
SET #num = #num+1
END
SET #sql = '
SELECT ' + #list + ' FROM testing'
EXEC(#sql)
OUTPUT:
val1 val3
1 1
1 1
1 1

Select columns based on values from any table(number of columns is variable) SQL

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

Dynamic declaration in tsql

is it possible to do dynamic declarations?
I will explain: I have a table COLUMNAMES:
ID|Name
1|Country
2|City
3|District
4|Neighbourhood
For each record in that table I would like to do something like:
declare #i int = 1
declare #number int
set #number = (SELECT count(*) FROM COLUMNNAMES)
While #i <= #number
BEGIN
Execute ('Declare column' + #i +'varchar(25)')
Execute ('set column' + #i +' = (Select NAME from COLUMNAMES where id = ' + #i)
set #i = #i + 1
END
The idea is that I get a list of variables (strings) that I can use to create SELECT statements with dynamic table-aliases:
Execute ('Select SOMECOLUMN as ' + #columname + #i +', ANOTHERCOLUMN as ' + #columname + #i +', ATHIRDCOLUMN as ' + #columname + #i + ' FROM SOMETABLE')
Can this be done? If so, how?
Each Execute function as a different session.
So, in order to declare the variable, all the code must be in one Execute function.
No you can't declare variables like this, but you can use a temporary table with the data filled in.
Here is some help, but it is not a whole solution, just an idea what you can do instead of the not working declaration:
Create Table #ColumnNames(
NAME varchar(64)
)
While #i <= #number
BEGIN
INSERT INTO #ColumNames
Select NAME from COLUMNAMES where id = #i
set #i = #i + 1
END
DECLARE #Columns varchar(max)
SET #Columns = ''
SElECT #Columns = #Columns + NAME + ', '
FROM #ColumNames
This is not complete solution but a direction . you need to get the value 'SomeColumn' dynamically someway ,likely the way you are getting the aliases in the below solution.
declare #i int = 1
declare #number INT
DECLARE #ColName VARCHAR(25)
DECLARE #SQL VARCHAR(4000)=''
DECLARE #ColumnsWithAlias VARCHAR(4000) = ''
set #number = (SELECT count(*) FROM COLUMNNAMES)
While #i <= #number
BEGIN
Select #ColName= NAME from COLUMNAMES where id = #i)
SET #ColumnsWithAlias =#ColumnsWithAlias + 'SomeColumn'+ ' AS '+ #ColName + ' , '
set #i = #i + 1
END
SET #SQL= 'SELECT '#ColumnsWithAlias+' FROM TableName'
EXECUTE(#SQL)

Cross Tab Query Required SQL 2000

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