Move multiple row values in a single row in SQL - sql

I have below table
TABLE A
| S | D |
----------
| 1 | 01 |
| 2 | 01 |
| 2 | 03 |
I want my query result in the below format
| S | D |
|1,2| 01 |
| 2 | 03 |
How can I get this in SQL

with the help of STUFF we can achieve this
declare #temp table
(
S int,
D nvarchar(10)
)
insert into #temp values (1,'01')
insert into #temp values (2,'01')
insert into #temp values (2,'03');
SELECT D,
STUFF(
(SELECT ',' + CAST(S AS VARCHAR(10))
FROM #temp
WHERE D = a.D
FOR XML PATH (''))
, 1, 1, '') AS Remark
FROM #temp AS a
GROUP BY D

Related

How to use a column as a key to pivot columns in SQL

I am trying to pivot a table and aggregate some sub-categories. However, when aggregating, the sub-categories aren't joining properly.
Example Table
| category | categorySub |
|----------|-------------|
| cat-1 | sub-1 |
| cat-1 | sub-2 |
| cat-1 | sub-3 |
| cat-2 | sub-4 |
| cat-2 | sub-5 |
Actual Output
| category | categorySub |
|----------|-------------------------------------------|
| cat-1 | ["sub-1","sub-2","sub-3","sub-4","sub-5"] |
| cat-2 | ["sub-1","sub-2","sub-3","sub-4","sub-5"] |
Desired Output
| category | categorySub |
|----------|---------------------------|
| cat-1 | ["sub-1","sub-2","sub-3"] |
| cat-2 | ["sub-4","sub-5"] |
Query
select
[categoryMain] = [category],
[categorySub] = '["' + (select string_agg(categorySub, '","') from someTable where [categoryMain] = [category]) + '"]'
from someTable
group by [category]
How can I reference [category] or its alias to pare down the string aggregation?
You can use that in STRING_AGG itself
DECLARE #T Table(
cat Varchar(max),
SUB varchar(max))
Insert into #T Values ('cat-1','sub-1')
Insert into #T Values ('cat-1','sub-2')
Insert into #T Values ('cat-1','sub-3')
Insert into #T Values ('cat-2','sub-4')
Insert into #T Values ('cat-2','sub-5')
SELECT CAT AS CATEGORYMAIN, '["' + STRING_AGG(SUB, '","')+ '"]' AS SUB
FROM #T GROUP BY [CAT]
As Martin suggested, we can use string_agg directly like:
select
[categoryMain] = [category],
[categorySub] = '["' + (select string_agg(categorySub, '","') + '"]'
from someTable
group by [category]

SQL query to get values of schema table row value in data table's column value

There are 2 database tables as shown below, Table_1 & Table_2.
Table_1 column index is match with id value of table_2.
Table_1
| date |city_1 | city_2 | ... | city_100 |
+-----------+-------+--------+-----+----------+
| 20.02.2018| 2 | 44 | ... | 98 |
| 21.02.2018| 1 | 25 | ... | 17 |
| ... | ... | ... | ... | ... |
Table_2
| id | name |
+-------+---------+
| 1 | newyork |
| 2 | london |
| ... | ... |
| 100 | istanbul|
Expected result is below
| date | city_1 | city_2 | ... | city_100 |
+-----------+------------+------------+-------+-----------+
| 20.02.2018| london | india | ... | canada |
| 21.02.2018| newyork | srilanka | ... | austria |
| ... | ... | ... | ... | ... |
What is the SQL query to get result above?
Thanks
You have to join Table_1 with Table_2 as many as many city columns you have, like this:
SELECT
t1.date, c1.name, c2.name, c3.name, ... c100.name
FROM Table_1 AS t1
JOIN Table_2 AS c1 ON t1.city_1 = c1.id
JOIN Table_2 AS c2 ON t1.city_2 = c2.id
JOIN Table_2 AS c3 ON t1.city_3 = c3.id
...
JOIN Table_2 AS c100 ON t1.city_100 = c100.id
If you are using Postgres, you can do something like this:
select data.id,
x.names[1] as city_name_1,
x.names[2] as city_name_2,
x.names[3] as city_name_3
from data
join lateral (
select array_agg(ct.name order by e.idx) as names
from unnest(array[city_1, city_2, city_3]) with ordinality as e(id, idx)
left join cities ct on e.id = ct.id
) x on true;
You still need to list all city "names" twice: once in the array inside the derived table, and once on the outside to get each name in a separate column.
If you can also live with a comma separated list of names you could use something like this:
select d.id,
string_agg(x.name, ',' order by x.idx) as names
from data d
join lateral (
select ct.name, e.idx
from unnest(array[city_1, city_2, city_3]) with ordinality as e(id, idx)
left join cities ct on e.id = ct.id
) x on true
group by data.id;
Or you can aggregate all the names into a single JSON value, then you don't need to hardcode any column name:
select d.id, x.names
from data d
join lateral (
select jsonb_object_agg(j.col, ct.name) as names
from cities ct
left join jsonb_each_text(to_jsonb(d) - 'id') as j(col, id) on j.id::int = ct.id
where j.col is not null
) x on true;
(I replaced your date column with an id column in my example)
Online example: https://rextester.com/NEBGX64778
In SQL Server (you haven't specified a DBMS), you could do something like this.
Sample table structure and data
CREATE TABLE sample (
date date, city_1 int, city_2 int, city_3 int, city_n int
);
INSERT INTO sample
VALUES
('2018-02-20', 4, 44, 98, ..),
('2018-02-21', 1, 25, 17, ..);
CREATE TABLE names (
id int,
name varchar(50)
);
INSERT INTO names
VALUES
(1, 'NewYork'),
(4, 'London'),
(17, 'Istanbul'),
(25, 'Colombo'),
(44, 'Vienna'),
(98, 'Helsinki');
Query 01
SELECT *
FROM (SELECT t1.date, t1.city, names.NAME
FROM (SELECT date, upvt.city, upvt.id
FROM sample
UNPIVOT ( id
FOR city IN (city_1, city_2, city_3, city_n) ) upvt) t1
INNER JOIN names ON t1.id = names.id) t2
PIVOT ( Min(NAME)
FOR city IN (city_1, city_2, city_3, city_n) ) AS pvt;
Query 01: Output
+----------------------+----------+----------+----------+----------+
| date | city_1 | city_2 | city_3 | city_n |
+----------------------+----------+----------+----------+----------+
| 20/02/2018 00:00:00 | London | Vienna | Helsinki | .... |
| 21/02/2018 00:00:00 | NewYork | Colombo | Istanbul | .... |
+----------------------+----------+----------+----------+----------+
Online Demo: https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=a14672b53b457d4ae59e6c9076cd9755
But if you don't want to write column names (city_1, city_2, city_n), then you can use this dynamic query.
Query 02: Get the column names
Example: city_1, city_2, city_n
SELECT column_name
FROM information_schema.columns
WHERE table_name = N'sample'
AND column_name LIKE 'city_%';
Query 02: Output
+-------------+
| column_name |
+-------------+
| city_1 |
| city_2 |
| city_3 |
+-------------+
Query 03: Dynamic Query
DECLARE #cols AS NVARCHAR(max),
#query AS NVARCHAR(max);
SET #cols = STUFF(( SELECT distinct ',' + QUOTENAME(column_name)
FROM information_schema.columns
WHERE table_name = N'sample' AND column_name LIKE 'city_%'
FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)') ,1,1,'');
SET #query = 'SELECT *
FROM (SELECT t1.date, t1.city, names.NAME
FROM (SELECT date, upvt.city, upvt.id
FROM sample
UNPIVOT (id
FOR city IN ('+ #cols +')) upvt) t1
INNER JOIN names ON t1.id = names.id) t2
PIVOT (Min(NAME)
FOR city IN ('+ #cols +')) AS pvt';
--select #query;
--select #cols;
execute(#query);
Query 03: Output
+----------------------+----------+----------+----------+
| date | city_1 | city_2 | city_3 |
+----------------------+----------+----------+----------+
| 20/02/2018 00:00:00 | London | Vienna | Helsinki |
| 21/02/2018 00:00:00 | NewYork | Colombo | Istanbul |
+----------------------+----------+----------+----------+
Online Demo: https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=e2d7f10a22a3e11044fc552ff73b14c5

Pivot Result Creation from SQL query using two tables and join

I have my first table like this, it contains platform and their platform code
+-----------+------+
| platforms | code |
+-----------+------+
| java | 1 |
| .net | 2 |
| perl | 3 |
+-----------+------+
My second table contains columns as shown below.
+-------+------+------+------+
| pname | code | year | deve |
+-------+------+------+------+
| a | 1 | 2018 | abia |
| b | 1 | 2017 | arun |
| c | 2 | 2018 | abia |
| d | 3 | 2017 | arun |
| e | 2 | 2017 | arun |
| f | 3 | 2018 | abia |
+-------+------+------+------+
Result expected in Pivot Format like this:
+-----+-------+------+------+------+
| year| deve | .net | java | perl |
+-----+-------+------+------+------+
| 2018| abia | 1 | 1 | 1 |
| 2017| arun | 1 | 1 | 1 |
+-----+-------+------+------+------+
Try this Pivot Script which meets your expectation
DECLARE #Table AS TABLE
(platforms VARCHAR(20), code INT)
INSERT INTO #Table
SELECT 'java', 1 UNION ALL
SELECT '.net', 2 UNION ALL
SELECT 'perl', 3
DECLARE #Table2 AS TABLE
(pname VARCHAR(20), code INT,[year] INT, deve VARCHAR(20))
INSERT INTO #Table2
SELECT 'a',1,2018,'abia' UNION ALL
SELECT 'b',1,2017,'arun' UNION ALL
SELECT 'c',2,2018,'abia' UNION ALL
SELECT 'd',3,2017,'arun' UNION ALL
SELECT 'e',2,2017,'arun' UNION ALL
SELECT 'f',3,2018,'abia'
SELECT [year],deve,MAX([java]) AS [java],MAX([.net]) AS [.net],MAX([perl] ) AS [perl]
FROM
(
SELECT platforms,CASE WHEN pname IS NOT NULL THEN 1 ELSE NUll END AS pname ,A.code ,deve,[year] FROM #Table2 A
INNER JOIN #Table B
ON A.code=b.code
)
AS SRC
PIVOT
(
MAX(pname) FOR platforms IN( [java],[.net],[perl] )
) AS PVT
GROUP BY [year],deve
Result
year deve java .net perl
------------------------------------
2018 abia 1 1 1
2017 arun 1 1 1
Pivot using dynamic sql approach as it fits when the columns to be added dynamically to get the specific result
CREATE TABLE #Table
(platforms VARCHAR(20), code INT)
INSERT INTO #Table
SELECT 'java', 1 UNION ALL
SELECT '.net', 2 UNION ALL
SELECT 'perl', 3
CREATE TABLE #Table2
(pname VARCHAR(20), code INT,[year] INT, deve VARCHAR(20))
INSERT INTO #Table2
SELECT 'a',1,2018,'abia' UNION ALL
SELECT 'b',1,2017,'arun' UNION ALL
SELECT 'c',2,2018,'abia' UNION ALL
SELECT 'd',3,2017,'arun' UNION ALL
SELECT 'e',2,2017,'arun' UNION ALL
SELECT 'f',3,2018,'abia'
DECLARE #Columns nvarchar(max),
#IsnullColumns nvarchar(max),
#Sql nvarchar(max)
SELECT #Columns= STUFF((SELECT ', '+QUOTENAME(platforms) FROM #Table FOR XML PATH ('')),1,1,'')
SELECT #IsnullColumns=STUFF((SELECT ', '+'MAX('+QUOTENAME(platforms)+') AS ' +QUOTENAME(platforms) FROM #Table FOR XML PATH ('')),1,1,'')
SET #Sql='
SELECT[year],deve, '+#IsnullColumns+'
FROM
( SELECT platforms,
CASE WHEN pname IS NOT NULL THEN 1 ELSE NUll END AS pname ,A.code ,deve,[year]
FROM #Table2 A
INNER JOIN #Table B
ON A.code=b.code
) AS SRC
PIVOT
(MAX(pname) FOR platforms IN('+#Columns+')
) AS PVT
GROUP BY [year],deve'
PRINT #Sql
EXEC (#Sql)
Result
year deve java .net perl
------------------------------------
2018 abia 1 1 1
2017 arun 1 1 1

trying to get more rows from the table than there actually exist

I was not sure about a descriptive Title of this question so I put there what i thought to be the best sentence.
I have a table like this:
StudentID, Month, Year, Present
-------------------------------
1, 1, 2016, P
1, 12, 2016, P
1, 4, 2017, P
I want to write SQL statement, without using cursor, to return a resultset like the below one:
Required output:
1, 1, 2016, P -- <-- it is 'P' in the table
1, 2, 2016, A
1, 3, 2016, A
1, 4, 2016, A
1, 5, 2016, A
1, 6, 2016, A
1, 7, 2016, A
1, 8, 2016, A
1, 9, 2016, A
1, 10, 2016, A
1, 11, 2016, A
1, 12, 2016, P -- <-- it is 'P' in the table
1, 1, 2017, A
1, 2, 2017, A
1, 3, 2017, A
1, 4, 2017, P -- <-- it is 'P' in the table
1, 5, 2017, A
1, 6, 2017, A
1, 7, 2017, A
1, 8, 2017, A
1, 9, 2017, A
1, 10, 2017, A
1, 11, 2017, A
1, 12, 2017, A
is this possible through one SQL statement, without using cursors.
I am working on SQL Server 2000 database.
You can generate numbers 1 to 12 using tally table and then do cross apply as below:
;with cte1 as
( select * from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) a(n) ) --number generation
,Cte_numbers as ( select num = Row_number() over (order by (SELECT NULL)) from cte1 c1, cte1 c2, cte1 c3)
Select s.StudentId, n.num as [Month], s.[Year], Coalesce(s1.Present,'A') as Present from (
Select distinct StudentId, [YEAR] from #student ) s
cross apply ( Select top (12) num from Cte_numbers ) n
left join #student s1
on s.StudentId = s1.StudentId
and s.[Year] = s1.[Year]
and n.num = s1.[Month]
order by s.StudentId, s.[Year]
You'll need to create tables for the missing entities. For instance, a Month entity with all months and Year with all years:
CREATE TABLE Month_Table (
Month_ID int NOT NULL,
PRIMARY KEY (Month_ID)
);
CREATE TABLE Year_Table (
Year_ID int NOT NULL,
PRIMARY KEY (Year_ID)
);
Fill Month_Table with numbers from 1 to 12, and Year_Table with numbers from 2016 to 2017.
Then use LEFT OUTER joins to fill the missing values with the ones provided by those tables. Use COALESCE to use the values from the auxiliary tables if your table doesn't contain them, and 'A' when your table doesn't contain the data:
SELECT T.StudentID,
COALESCE(T.Month, Month_Table.Month_ID) Month,
COALESCE(T.Year, Year_Table.Year_ID) Year,
COALESCE(T.Present, 'A') Present
FROM YOUR_TABLE T
LEFT OUTER JOIN Month_Table ON Month_Table.Month_ID = YOUR_TABLE
LEFT OUTER JOIN Year_Table ON Year_Table.Year_ID = YOUR_TABLE.Year;
Here's two examples, one that uses CTEs, recursion, etc. just to show how easy this is in SQL Server 2005 onwards, then an example that should work in SQL Server 2000.
Like all the other answers this is basically using a numbers or tally table to do the heavy lifting. There's a good article on how to generate numbers here: https://sqlperformance.com/2013/01/t-sql-queries/generate-a-set-1
DECLARE #MyData TABLE (StudentId INT, [Month] INT, [Year] INT, Present CHAR(1));
INSERT INTO #MyData SELECT 1, 1, 2016, 'P';
INSERT INTO #MyData SELECT 1, 12, 2016, 'P';
INSERT INTO #MyData SELECT 1, 4, 2017, 'P';
--Recursive CTE to load numbers table dynamically
WITH Numbers AS (
SELECT 1 AS [Month], 2016 AS [Year]
UNION ALL
SELECT CASE WHEN [Month] = 12 THEN 1 ELSE [Month] + 1 END, CASE WHEN [Month] = 12 THEN [Year] + 1 ELSE [Year] END
FROM Numbers
WHERE [Year] < 2017 OR [Month] < 12),
Students AS (
SELECT DISTINCT StudentId FROM #MyData)
SELECT
s.StudentId,
n.[Year],
n.[Month],
ISNULL(m.Present, 'A') AS Present
FROM
Students s
CROSS JOIN Numbers n
LEFT JOIN #MyData m ON m.StudentId = s.StudentId AND m.[Year] = n.[Year] AND m.[Month] = n.[Month]
OPTION (MAXRECURSION 0);
--SQL Server 2000 doesn't have CTEs so we have to use a different method
DECLARE #Numbers TABLE ([Year] INT, [Month] INT);
DECLARE #Year INT = 2016;
WHILE #Year < 2018
BEGIN
DECLARE #Month INT = 1;
WHILE #Month < 13
BEGIN
INSERT INTO #Numbers SELECT #Year, #Month;
SELECT #Month = #Month + 1;
END;
SELECT #Year = #Year + 1;
END;
--SQL Server 2000 query
SELECT
s.StudentId,
n.[Year],
n.[Month],
ISNULL(m.Present, 'A') AS Present
FROM
(SELECT DISTINCT StudentId FROM #MyData) s
CROSS JOIN #Numbers n
LEFT JOIN #MyData m ON m.StudentId = s.StudentId AND m.[Year] = n.[Year] AND m.[Month] = n.[Month];
I think you can do it, by creating a table (tally) with all year-month you'll need.
Sample data:
CREATE TABLE TD1 (YYEAR SMALLINT, MMONTH SmALLINT);
INSERT INTO TD1 VALUES (2016,1);
INSERT INTO TD1 VALUES (2016,2);
INSERT INTO TD1 VALUES (2016,3);
INSERT INTO TD1 VALUES (2016,4);
INSERT INTO TD1 VALUES (2016,5);
INSERT INTO TD1 VALUES (2016,6);
INSERT INTO TD1 VALUES (2016,7);
INSERT INTO TD1 VALUES (2016,8);
INSERT INTO TD1 VALUES (2016,9);
INSERT INTO TD1 VALUES (2016,10);
INSERT INTO TD1 VALUES (2016,11);
INSERT INTO TD1 VALUES (2016,12);
INSERT INTO TD1 VALUES (2017,1);
INSERT INTO TD1 VALUES (2017,2);
INSERT INTO TD1 VALUES (2017,3);
INSERT INTO TD1 VALUES (2017,4);
INSERT INTO TD1 VALUES (2017,5);
INSERT INTO TD1 VALUES (2017,6);
INSERT INTO TD1 VALUES (2017,7);
INSERT INTO TD1 VALUES (2017,8);
INSERT INTO TD1 VALUES (2017,9);
INSERT INTO TD1 VALUES (2017,10);
INSERT INTO TD1 VALUES (2017,11);
INSERT INTO TD1 VALUES (2017,12);
CREATE TABLE TS1 (StudentId INT, MMONTH SMALLINT, YYEAR SMALLINT, PRESENT CHAR(1))
INSERT INTO TS1 VALUES (1,1,2016,'P');
INSERT INTO TS1 VALUES (1,12,2016,'P');
INSERT INTO TS1 VALUES (1,4,2017,'P');
INSERT INTO TS1 VALUES (2,3,2017,'P');
Query:
SELECT A.STUDENTID, TD1.MMONTH, TD1.YYEAR, COALESCE(TS1.PRESENT, 'A') AS PRESENT
FROM TD1
CROSS JOIN (SELECT DISTINCT STUDENTID FROM TS1) A
LEFT JOIN TS1 On TD1.MMONTH=TS1.MMONTH AND TD1.YYEAR=TS1.YYEAR AND A.STUDENTID = TS1.STUDENTID
ORDER BY A.STUDENTID, TD1.YYEAR, TD1.MMONTH;
Output:
+-----------+--------+-------+---------+
| STUDENTID | MMONTH | YYEAR | PRESENT |
+-----------+--------+-------+---------+
| 1 | 1 | 2016 | P |
| 1 | 2 | 2016 | A |
| 1 | 3 | 2016 | A |
| 1 | 4 | 2016 | A |
| 1 | 5 | 2016 | A |
| 1 | 6 | 2016 | A |
| 1 | 7 | 2016 | A |
| 1 | 8 | 2016 | A |
| 1 | 9 | 2016 | A |
| 1 | 10 | 2016 | A |
| 1 | 11 | 2016 | A |
| 1 | 12 | 2016 | P |
| 1 | 1 | 2017 | A |
| 1 | 2 | 2017 | A |
| 1 | 3 | 2017 | A |
| 1 | 4 | 2017 | P |
| 1 | 5 | 2017 | A |
| 1 | 6 | 2017 | A |
| 1 | 7 | 2017 | A |
| 1 | 8 | 2017 | A |
| 1 | 9 | 2017 | A |
| 1 | 10 | 2017 | A |
| 1 | 11 | 2017 | A |
| 1 | 12 | 2017 | A |
| 2 | 1 | 2016 | A |
| 2 | 2 | 2016 | A |
| 2 | 3 | 2016 | A |
| 2 | 4 | 2016 | A |
| 2 | 5 | 2016 | A |
| 2 | 6 | 2016 | A |
| 2 | 7 | 2016 | A |
| 2 | 8 | 2016 | A |
| 2 | 9 | 2016 | A |
| 2 | 10 | 2016 | A |
| 2 | 11 | 2016 | A |
| 2 | 12 | 2016 | A |
| 2 | 1 | 2017 | A |
| 2 | 2 | 2017 | A |
| 2 | 3 | 2017 | P |
| 2 | 4 | 2017 | A |
| 2 | 5 | 2017 | A |
| 2 | 6 | 2017 | A |
| 2 | 7 | 2017 | A |
| 2 | 8 | 2017 | A |
| 2 | 9 | 2017 | A |
| 2 | 10 | 2017 | A |
| 2 | 11 | 2017 | A |
| 2 | 12 | 2017 | A |
+-----------+--------+-------+---------+

Join Vertical & Horizontal table in SQL Server using Pivot

I want to join two tables and combine into one but problem is one table is in Horizontal Format and other in Vertical format.
below is the table structure and join will be on Employeeid:
Table 1 : EmpDetail
ID | CODE | Name
-- |--------| ---
1 | 1008M | ABC
2 | 1039E | XYZ
3 | 1040E | TYS
Table 2 : EmpCustomeDetail
EmpID | FiledName | FieldValue
-- |-------- | ---
1 | FlD1 | temp1
1 | FlD2 | temp2
1 | FlD3 | temp3
2 | FlD1 | temp1
3 | FLD4 | temp6
Desired Output Required :
EmpID | Code | Name | Fld1 | Fld2 | Fld3 | Fld4
-- |---- | ------| --- | ---- |---- |----
1 | 1008M | ABC | temp1 | temp2 | temp3 | null
2 | 1039E | XYZ | temp1 | null | null | null
3 | 1040E | TYS | null | null | null | temp6
I had tried using Pivot Query but it is not giving exact output which i requried
Below is the query so far i have tried
SELECT A.*
FROM (
SELECT
e.Id,
e.code,
e.Fname,
FROM EmpDetail e
LEFT JOIN (
SELECT *
FROM (
SELECT
d.CustomeFieldName
, c.ComboValue
, d.EmployeeId
FROM EmpCustomeDetail d
) src
PIVOT (
MAX(FieldValue)
) src2
) c ON e.Id = c.EmployeeId
) A
Here are two statements:
The first is a simple PIVOT. You can use it, in case you know all Fieldnames (btw: there's a typo in your sample) in advance.
The second is roughly the same statement, but the column names are taken dynamically. This will work with (almost) any count and with different namings.
First a mock-up-test-scenraio
CREATE TABLE DummyEmpDetail (ID INT,CODE VARCHAR(10),Name VARCHAR(100));
INSERT INTO DummyEmpDetail VALUES
(1,'1008M','ABC')
,(2,'1039E','XYZ')
,(3,'1040E','TYS');
CREATE TABLE DummyEmpCustomeDetail (EmpID INT,FiledName VARCHAR(100),FieldValue VARCHAR(100));
INSERT INTO DummyEmpCustomeDetail VALUES
(1,'FlD1','temp1')
,(1,'FlD2','temp2')
,(1,'FlD3','temp3')
,(2,'FlD1','temp1')
,(3,'FLD4','temp6');
--The static PIVOT statement
SELECT p.EmpID
,p.Name
,p.CODE
,p.Fld1
,p.Fld2
,p.Fld3
p,Fld4
FROM
(
SELECT e.CODE,e.Name,ec.*
FROM DummyEmpDetail AS e
INNER JOIN DummyEmpCustomeDetail AS ec ON e.ID=ec.EmpID
) AS tbl
PIVOT
(
MAX(FieldValue) FOR FiledName IN(Fld1,Fld2,Fld3,Fld4)
) AS p;
--The dynamic PIVOT statement
DECLARE #colNames VARCHAR(MAX)=
(
STUFF
(
(
SELECT DISTINCT ',' + QUOTENAME(FiledName) FROM DummyEmpCustomeDetail
FOR XML PATH('')
),1,1,''
)
);
DECLARE #command VARCHAR(MAX)=
'SELECT p.EmpID
,p.Name
,p.CODE
,' + #colNames +
' FROM
(
SELECT e.CODE,e.Name,ec.*
FROM DummyEmpDetail AS e
INNER JOIN DummyEmpCustomeDetail AS ec ON e.ID=ec.EmpID
) AS tbl
PIVOT
(
MAX(FieldValue) FOR FiledName IN(' + #colnames + ')
) AS p;';
EXEC (#command);
GO
DROP TABLE DummyEmpCustomeDetail;
DROP TABLE DummyEmpDetail;
Both lead to the same result...
Try like below. If values of fieldname will not be static then you should use dynamic sql.
SELECT EMPID,
CODE,
NAME,
FLD1,
FLD2,
FLD3,
FLD4
FROM EmpDetail C
JOIN (SELECT A.*
FROM EmpCustomeDetail
PIVOT ( MIN([FIELDVALUE])
FOR [FILEDNAME] IN([FLD1],
[FLD3],
[FLD2],
FLD4) )A)B
ON C.ID = B.[EMPID]
No need for sub-queries.
select e.*,FlD1,FlD2,FlD3,FlD4
from EmpDetail e
left join EmpCustomeDetail
pivot (max(FieldValue) for FiledName in (FlD1,FlD2,FlD3,FlD4)) ecd
on ecd.EmpID = e.ID
+----+-------+------+-------+-------+-------+-------+
| ID | CODE | Name | FlD1 | FlD2 | FlD3 | FlD4 |
+----+-------+------+-------+-------+-------+-------+
| 1 | 1008M | ABC | temp1 | temp2 | temp3 | NULL |
+----+-------+------+-------+-------+-------+-------+
| 2 | 1039E | XYZ | temp1 | NULL | NULL | NULL |
+----+-------+------+-------+-------+-------+-------+
| 3 | 1040E | TYS | NULL | NULL | NULL | temp6 |
+----+-------+------+-------+-------+-------+-------+