edgarmtze
edgarmtze

Reputation: 25058

Layout sql server

I have a table like

att1 att2 att3 att4
-------------------
1    6    11    16
2    7    12    17 
3    8    13    18
4    9    14    19 

What is the query to get the table as a coordinate system as:

a b val
-------
1 1  1
1 2  6 
1 3  11
1 4  16
2 1  2
2 2  7 
2 3  12
2 4  17
3 1  3
3 2  8
3 3  13
3 4  18
4 1  4
4 2  9
4 3  14
4 4  19

Currently I have:

select 1,att1 from data_journal_insurance_raw union all
select 2,att2 from data_journal_insurance_raw union all
select 3,att3 from data_journal_insurance_raw union all
select 4,att4 from data_journal_insurance_raw

I am missing the 'b' part how to do it?

Upvotes: 0

Views: 71

Answers (2)

Peter
Peter

Reputation: 1065

If I understand you correctly, you want to convert the table into a table containing Row, Column and Value.

Actually, you're missing the a part. a represents the row, and b the column. The following query should help you.

WITH cte AS (SELECT ROW_NUMBER() OVER (ORDER BY att1) AS a, * FROM data_journal_insurance_raw)
SELECT a, 1 as b, CAST(att1 AS VARCHAR(MAX)) FROM cte UNION ALL
SELECT a, 2 as b, CAST(att2 AS VARCHAR(MAX)) FROM cte UNION ALL
SELECT a, 3 as b, CAST(att3 AS VARCHAR(MAX)) FROM cte UNION ALL
SELECT a, 4 as b, CAST(att4 AS VARCHAR(MAX)) FROM cte
ORDER BY a, b

Notice that I'm casting the value column to VARCHAR(MAX), because I don't know what data types you have in your table. If they're all numeric, then you can drop the CAST functions.

If you're only doing this once on a single table, then this will work fine for you. However, if you want to be able to do this on various tables, you can make SQL Server write the code for you. Here's a procedure that will do just that:

CREATE PROCEDURE usp_Coordinate_table(@TableName NVARCHAR(200)) AS
BEGIN
    DECLARE @sql NVARCHAR(MAX);
    WITH cte AS (SELECT TOP 1 c.name FROM sys.columns c, sys.objects o WHERE c.object_id = o.object_id AND o.name = @TableName)
    SELECT @sql = 'WITH RowData AS (SELECT ROW_NUMBER() OVER (ORDER BY '+name+') AS RowNum, * FROM '+@TableName+') ' FROM cte;

    WITH ColData AS (SELECT ROW_NUMBER() OVER (ORDER BY c.column_id) AS ColNum, c.name 
        FROM sys.columns c, sys.objects o WHERE c.object_id = o.object_id AND o.name = @TableName)
    SELECT @sql = @sql + 'SELECT RowNum, '+CAST(c.ColNum AS VARCHAR)+' AS ColNum, CAST('+c.name+' AS VARCHAR(MAX)) AS Value FROM RowData UNION ALL '
    FROM ColData c

    SET @sql = SUBSTRING(@sql, 1, LEN(@sql) - 10) + ' ORDER BY RowNum, ColNum'
    EXEC sp_executesql @sql
END

Upvotes: 1

Mahdi jokar
Mahdi jokar

Reputation: 1267

You should to have 3 column in Union

select att1 ,1,att1 from data_journal_insurance_raw union
select att1 ,2,att2 from data_journal_insurance_raw union
select att1 ,3,att3 from data_journal_insurance_raw union
select att1 ,4,att4 from data_journal_insurance_raw

Upvotes: 0

Related Questions