I know this might have been asked before but I really could not find the answer. I have a temporary table named #TEMP which looks like this:
+===============================+=============================+
| NAME | ATTRIBUTE |
+===============================+=============================+
| BadgeType | Permanent |
+-------------------------------+-----------------------------+
| PrimaryLocationInCompany | No |
+-------------------------------+-----------------------------+
| AdminAccessToProductionServer | No |
+-------------------------------+-----------------------------+
| AccessToImportantFIles | No |
+-------------------------------+-----------------------------+
| Waiver_Number | 56987 |
+-------------------------------+-----------------------------+
| Summary | User not much active |
+-------------------------------+-----------------------------+
| TimeStamp | 3/3/2009 |
+-------------------------------+-----------------------------+
| UserID | 86478925 |
+-------------------------------+-----------------------------+
What I want to do is to transpose both the Name and Attribute values to rows. The Attribute values may vary but the Name values are always fixed.
The result should look like this:
+----------+---------------+------------------------------+--------------------------------+-----------------------+--------------------------------------------------------+----------+-----------+
| UserID | BadgeType | PrimaryLocationIntelFacility | adminAccessToProductionServer | AccessToClassifiedData| Info_Sec_Waiver_Number | Summary | TimeStamp |
+----------+---------------+------------------------------+--------------------------------+-----------------------+--------------------------------------------------------+----------+-----------+
| 11313403 | GREEN | No | No | No | This contingent worker is eligible for remote access. | 3/3/2009 | |
+----------+---------------+------------------------------+--------------------------------+-----------------------+--------------------------------------------------------+----------+-----------+
Try this
SELECT UserID,BadgeType,PrimaryLocationInCompany,AdminAccessToProductionServer,AccessToImportantFIles,WaiverNumber,Summary,[TimeStamp]
FROM
(
SELECT * FROM #Temp
) p
PIVOT
(
MIN([ATTRIBUTE]) FOR [NAME] IN(BadgeType,PrimaryLocationInCompany,AdminAccessToProductionServer,AccessToImportantFIles,WaiverNumber,Summary,[TimeStamp],UserID)
) T
Also check the below for dynamic columns
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + [NAME]
from #Temp
group by [NAME]
FOR XML PATH(''))
,1,1,'')
set #query = 'SELECT ' + #cols + ' from
(
select * from #Temp
) x
pivot
(
MAX([ATTRIBUTE])
for [NAME] in (' + #cols + ')
) p '
execute(#query)
Related
I have this code
DECLARE #cols AS NVARCHAR(MAX), #vals AS NVARCHAR(MAX), #query AS NVARCHAR(MAX)
SELECT #cols = STUFF(( SELECT ',' + x.Name
FROM (
SELECT Name FROM Persons)x
FOR xml PATH(''), TYPE
).value('.','NVARCHAR(MAX)')
,1,1,'')
SELECT #vals = STUFF((SELECT ','+y.Column
FROM (
SELECT CONVERT (varchar, x.Subject) Column FROM subjects x) y
FOR XML PATH (''), TYPE).value('.','NVARCHAR(MAX)'),1,1,'')
SELECT #vals
SET #query = 'SELECT d.id, d.val Column, e.val Value
FROM (SELECT * FROM dbo.Split('''+#cols+''','','')) d,
(SELECT * FROM dbo.Split('''+#vals+''', '','')) e
WHERE d.id = e.id'
That convert to a separate string with commas (WITH STUFF), and then pass it to a column(val) defined by a split function. Convert all the Names into a string separated by commas [Paco, Juan, Pepe, Maria] and returns it to column BUT
I want that a row of a table to be separated by commas [Paco, Perez, Ingles] [Juan, Hernandez, Historia], to later pass it to a column. Something like that:
|ID | Name | LastName | Subject | |ID | Col | Col |
| - | ----- | -------- | --------- | | - | ----- | ------- |
| 1 | Paco | Perez | English | ------>| 1 | Paco | Juan |
| 2 | Juan | Hernandez| History | ------>| 2 | Perez |Hernandez|
| 3 | Pepe | Salas | Spanish | | 3 |English|vHistory |
| 4 | MAria | Cruz | Arts |
I'm trying to pivot a table from the format
| ID | access date |
--------------
| 1 | 08.10|
| 1 | 08.10|
| 4 | 08.10|
| 2 | 02.09|
To
|ID | 02.09 | 03.09 | 04.09 | ....
| 1 | 4 | 0 | 2 |
| 2 | 1 | 2 | 5 |
| 3 |
.
.
.
I've tried using the PIVOT function but since I have a lot of different dates I don't want to type out the query
SELECT *
FROM (
SELECT [Sequence of events] as ID
,[Submission Date] as access_date
FROM [database_name].[dbo].[Event Logging]
) AS SOURCE_TABLE
PIVOT( SUM(ID) for access_date IN ("08.01", "09.01", "10.01"....)
) as pvt_table
I'm very new to SQL so I'd appreciate some insight into how to solve this problem.
This is not answer about solving problem in your way but it is about solving it another way.
What i would do is create 2 tables. First one would be called DATE_DB where i would store DATEID and DATE and it would look like this:
| DATEID | DATE |
| 1 | 01.01|
| 2 | 02.02|
....
Then in second table I store data like this:
| ID | DATEID | VALUE |
| 1 | 2 | 10 |
| 2 | 2 | 3 |
| 3 | 3 | 4 |
| 4 | 2 | 5 |
So in second table column ID is used only for primary key and has nothing to do but with tables like this and JOIN command you can use it like this:
SELECT DATE_DB.DATE, SECONDTABLE.VALUE
FROM SECONDTABLE
LEFT JOIN DATE_DB ON SECONDTABLE.DATEID = DATE_DB.DATE
ORDER BY DATE_DB.DATE
which will display result like this:
| DATE | VALUE |
| 02.01 | 10 |
| 02.01 | 3 |
| 02.01 | 5 |
| 03.01 | 4 |
Try it out like this, you need dynamic sql, note script isn't tested out, also when you naming your columns try not to have space, ether use CamelCase or underscore to separate words
And last thing, this is for SQL-Server, as you didn't tag anything and your code looks like sql-server
declare #cols nvarchar(max)
select #cols = STUFF((SELECT DISTINCT ',' + QUOTENAME([Submission Date])
from [database_name].[dbo].[Event Logging]
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
declare #sql nvarchar(max);
set #sql = '
SELECT *
FROM (
SELECT [Sequence of events] as ID
,[Submission Date] as access_date
FROM [database_name].[dbo].[Event Logging]
) AS SOURCE_TABLE
PIVOT( SUM(ID) for access_date IN (' + #cols + ')
) as pvt_table';
-- print (#sql)
execute (#sql)
I have to work on a mapping from an ERP system to a MySQL database. The structure that is present in the ERP system is:
_____________________________________
| Article | Feature | Criterion |
|---------|---------------|-----------|
| Art1 | size | 4*10 |
| Art1 | color | red |
| Art1 | functionality | doesA |
| Art1 | ... | ... |
| Art2 | size | 2*5 |
| Art2 | color | green |
| Art2 | functionality | doesB |
| Art2 | ... | ... |
-------------------------------------
What i need to do is map it like this:
________________________________________________
| Article | size | color | functionality | ... |
|---------|------|-------|---------------|-------|
| Art1 | 4*10 | red | doesA | ... |
| Art2 | 2*5 | green | doesB | ... |
------------------------------------------------
I can access the ERP system via T-SQL and can perform a working dynamic query, that provides me a table and looks like:
DECLARE #cols AS nvarchar(MAX),
#query AS nvarchar(MAX)
SELECT #cols = stuff((SELECT DISTINCT ', ' + quotename(f.Feature) + ''
FROM CRITERION c, FEATURE f
WHERE --necessary joins
FOR xml PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #query = N'SELECT Article, ' + #cols + N'
FROM (
SELECT Article, Feature, Criterion
FROM --necessary tables
WHERE --necessary joins
) x
pivot
(
max(Criterion)
FOR Feature IN (' + #cols + N')
) p
'
EXEC sp_executesql #query;
The problem that is coming up now is, that the system features multiple selection for some of the features:
_____________________________________
| Article | Feature | Criterion |
|---------|---------------|-----------|
| Art3 | color | red |
| Art3 | color | green |
-------------------------------------
and the query just gives me the first result in the table.
________________________________________
| Article | size | color | functionality |
|---------|------|-------|---------------|
| Art3 | ... | red | ... |
----------------------------------------
So my question is, if there is any way to add a string concatenation either in the subquery 'x' or in the pivot table 'p', so the result becomes following:
_____________________________________________
| Article | size | color | functionality |
|---------|------|------------|---------------|
| Art3 | ... | red, green | ... |
---------------------------------------------
#Serg has the right idea but the fields seem to be off. This should be closer.
SET #query = N'
SELECT Article, ' + #cols + N'
FROM (
SELECT Article,
Feature,
Criterion = STUFF(
(SELECT '', '' + t2.Criterion
FROM t1 as t2
WHERE t2.Article = t1.Article
AND t2.[Feature] = t1.[Feature]
FOR XML PATH('''')), 1, 2,'''')
FROM (SELECT Article, Feature, Criterion
FROM --necessary tables
WHERE --necessary joins) t1
) x
pivot
(
MAX(Criterion)
FOR Feature IN (' + #cols + N')
) p
'
GROUP BY features first using the same FOR XML trick. Kind of
SET #query = N'SELECT Article, ' + #cols + N'
FROM (
SELECT Article, Criterion,
Feature = stuff(
(SELECT '',''+ t2.Feature
FROM ttt as t2
WHERE t2.Article = t1.Article AND
t2.Criterion = t1.Criterion
FOR XML PATH(''))
,1,1,'''')
FROM ttt t1
GROUP BY Article, Criterion
) x
pivot
(
max(Criterion)
FOR Feature IN (' + #cols + N')
) p
'
Replace ttt with real data sources.
After trying it myself for some hours now I need to ask for help. I only did some basic SQL until now.
I want to solve the following:
(I have translated a couple of things for you to understand the context)
I have three tables:
Workers (Mitarbeiter in German - mitID)
| mitID | Name | FamName | DOB | abtIDref |
|-------|--------|---------|------------|----------|
| 1 | Frank | Sinatra | 12.12.1915 | 1 |
| 2 | Robert | Downey | 4.4.1965 | 2 |
INFO: abtIDref is an 1:n relation for the Workplace, but not involved here
Skills (Faehigkeiten in German - faeID)
| faeID | Descr | time | cost |
|-------|-------|------|------|
| 1 | HV | 2 | 0 |
| 2 | PEV | 1 | 0 |
| 3 | Drive | 8 | 250 |
| 4 | Nex | 20 | 1200 |
Link-List
| linkID | mitIDref | feaIDref | when |
|--------|----------|----------|------------|
| 1 | 2 | 1 | 27.07.2014 |
| 2 | 2 | 2 | 01.01.2016 |
| 3 | 2 | 3 | 20.01.2016 |
| 4 | 1 | 3 | 05.06.2015 |
| 5 | 1 | 4 | 02.11.2015 |
The desired result is:
| mitID | Name | FamName | DOB | abtIDref | HV | PEV | Drive | Nex |
|-------|--------|---------|------------|----------|-----------|------------|------------|------------|
| 1 | Frank | Sinatra | 12.12.1915 | 1 | | | 05.06.2015 | 02.11.2015 |
| 2 | Robert | Downey | 4.4.1965 | 2 | 27.7.2014 | 01.01.2016 | 20.01.2015 | |
Alternative it could be:
| mitID | Name | FamName | DOB | abtIDref | HV | PEV | Drive | Nex |
|-------|--------|---------|------------|----------|----|-----|-------|-----|
| 1 | Frank | Sinatra | 12.12.1915 | 1 | | | x | x |
| 2 | Robert | Downey | 4.4.1965 | 2 | x | x | x | |
The goal is that users/admins can add up new skills and someone can see on this resultlist, if a person has this skill.
What did i try:
I've come across multiple examples of dynamic SQL and the pivot function, but I don't know how to use it in my case, because I don't run a function like AVG() or MIN().
I tried it like this:
DECLARE #columns AS VARCHAR(MAX);
DECLARE #sql AS VARCHAR(MAX);
select #columns = substring((Select DISTINCT ',' + QUOTENAME(faeID) FROM mdb_Fähigkeiten FOR XML PATH ('')),2, 1000);
SELECT #sql = 'SELECT * FROM mdb_Mitarbeiter
PIVOT
(
MAX(Value)
FOR mitID IN( ' + #columns + ' )
);';
execute(#sql);
And a second approach was:
declare #collist nvarchar(max)
SET #collist = stuff((select distinct ',' + QUOTENAME(Question)
FROM #t1 -- your table here
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
select #collist
declare #q nvarchar(max)
set #q = '
select *
from (
select
Vorname, Bezeichnung, faeIDref
from (
select #t1.*, #t2.Answer, #t2.parent
from #t1
inner join #t2 on #t1.QID = #t2.QID
) as x
) as source
pivot (
max(Answer)
for Question in (' + #collist + ')
) as pvt
'
exec (#q)
But TBH I don't get the functions found.
I hope you can provide me with some guidance what I have to change (or even if I can) achieve this.
I believe the query below is what you are looking for. Adjust the column and table names as needed to fit your database.
DECLARE #sql AS NVARCHAR(MAX)
DECLARE #cols AS NVARCHAR(MAX)
SELECT #cols= ISNULL(#cols + ',','') + QUOTENAME(Descr)
FROM Faehigkeiten ORDER BY faeID
SET #sql = N'
SELECT mitID, Name, FamName, DOB, abtIDref, ' + #cols + '
FROM (
SELECT mitID, Name, FamName, DOB, abtIDref, [when], descr
FROM Mitarbeiter m
JOIN [Link-List] l ON m.mitID = l.mitIDref
JOIN Faehigkeiten f ON f.faeID = l.feaIDref
) a
PIVOT(MAX([when]) FOR descr IN (' + #cols + ')) p'
EXEC sp_executesql #sql
I have the following dataset on a sql database
----------------------------------
| ID | NAME | AGE | STATUS |
-----------------------------------
| 1ASDF | Brenda | 21 | Single |
-----------------------------------
| 2FDSH | Ging | 24 | Married|
-----------------------------------
| 3SDFD | Judie | 18 | Widow |
-----------------------------------
| 4GWWX | Sophie | 21 | Married|
-----------------------------------
| 5JDSI | Mylene | 24 | Singe |
-----------------------------------
I want to query that dataset so that i can have this structure in my result
--------------------------------------
| AGE | SINGLE | MARRIED | WIDOW |
--------------------------------------
| 21 | 1 | 1 | 0 |
--------------------------------------
| 24 | 1 | 1 | 0 |
--------------------------------------
| 18 | 0 | 0 | 1 |
--------------------------------------
And the status column can be dynamic so there will be more columns to come.
Is this possible?
Since you are using SQL Server, you can use the PIVOT table operator like this:
SELECT *
FROM
(
SELECT Age, Name, Status FROM tablename
) AS t
PIVOT
(
COUNT(Name)
FOR Status IN(Single, Married, Widow)
) AS p;
SQL Fiddle Demo
To do it dynamically you have to use dynamic sql like this:
DECLARE #cols AS NVARCHAR(MAX);
DECLARE #query AS NVARCHAR(MAX);
select #cols = STUFF((SELECT distinct ',' +
QUOTENAME(status)
FROM tablename
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '');
SELECT #query = '
SELECT *
FROM
(
SELECT Age, Name, Status FROM tablename
) AS t
PIVOT
(
COUNT(Name)
FOR Status IN( ' +#cols + ')
) AS p;';
execute(#query);
Updated SQL Fiddle Demo