SQL Server Converts rows to columns dynamic columns - sql-server

I have the following table
family
id name
-------------
1 Joe
1 Jim
1 Jane
2 Matt
2 Pat
3 Gary
3 Mike
Would like to get to
id name1, name2, name3, name4 ....
1 Joe Jim Jane
2 Matt Pat
3 Gary Mike.
Can this be done using PIVOT?

SQL Fiddle
MS SQL Server 2008 Schema Setup:
CREATE TABLE Test_TABLE(id INT, name VARCHAR(10))
GO
INSERT INTO Test_TABLE VALUES
(1 ,'Joe'),(1 ,'Jim'),(1 ,'Jane'),
(2 ,'Matt'),(2 ,'Pat'),(3 ,'Gary')
GO
Query 1:
SELECT * FROM
(
SELECT *
,'Name' + CAST(ROW_NUMBER() OVER (PARTITION BY ID ORDER BY ID ASC) AS VARCHAR(3)) Names
FROM Test_TABLE )t
PIVOT (MAX(Name)
FOR Names
IN (Name1,Name2,Name3)
)p
Results:
| ID | NAME1 | NAME2 | NAME3 |
|----|-------|--------|--------|
| 1 | Joe | Jim | Jane |
| 2 | Matt | Pat | (null) |
| 3 | Gary | (null) | (null) |

Related

SSIS Lookup Multiple Columns in one table to the same ID column in another

I have the following table:
EventValue | Person1 | Person2 | Person3 | Person4 | Meta1 | Meta2
-------------------------------------------------------------------------------------------
123 | joePerson01 | samRock01 | nancyDrew01 | steveRogers01 | 505 | 606
321 | steveRogers02 | yoMama01 | ruMo01 | lukeJedi01 | 707 | 808
I want to transform the Person columns into IDs for my destination table, so all of the ID's would be coming from the same Person table in my Destination DB:
ID | FirstName | LastName | DatabaseOneID | DatabaseTwoID
----------------------------------------------------------
1 | Joe | Person | joePerson01 | personJoe01
2 | Sam | Rockwell | samRock01 | rockSam01
3 | Nancy | Drew | nancyDrew01 | drewNancy01
4 | Steve | Rogers | steveRogers01 | rogersSteve01
5 | Steve R | Rogers | steveRogers02 | rogersSteve02
6 | Yo | Mama | yoMama01 | mamaYo01
7 | Rufus | Murdock | ruMo01 | moRu01
8 | Luke | Skywalker | lukeJedi01 | jediLuke01
With results like so:
MetaID | EventValue | Person1ID | Person2ID | Person3ID | Person4ID
------------------------------------------------------------------------
1 | 123 | 1 | 2 | 3 | 4
2 | 321 | 5 | 6 | 7 | 8
I currently have a Lookup Transform looking up the first Person column, but couldn't figure out how to convert all 4 Person columns into IDs within the same lookup.
You could do it in one query, or use UNPIVOT, or use a scalar function if you think it'll be more fixable for your implementation. Then, you just create a view of it, in which it'll be an easy access for you.
here is a quick example :
DECLARE
#tb1 TABLE
(
EventValue INT
, Person1 VARCHAR(250)
, Person2 VARCHAR(250)
, Person3 VARCHAR(250)
, Person4 VARCHAR(250)
, Meta1 INT
, Meta2 INT
)
DECLARE
#Person TABLE
(
ID INT
, FirstName VARCHAR(250)
, LastName VARCHAR(250)
, DatabaseOneID VARCHAR(250)
, DatabaseTwoID VARCHAR(250)
)
INSERT INTO #tb1
VALUES
(123,'joePerson01','samRock01','nancyDrew01','steveRogers01',505,606),
(321,'steveRogers02','yoMama01','ruMo01','lukeJedi01',707,808)
INSERT INTO #Person
VALUES
(1,'Joe','Person','joePerson01','personJoe01'),
(2,'Sam','Rockwell','samRock01','rockSam01'),
(3,'Nancy','Drew','nancyDrew01','drewNancy01'),
(4,'Steve','Rogers','steveRogers01','rogersSteve01'),
(5,'SteveR','Rogers','steveRogers02','rogersSteve02'),
(6,'Yo','Mama','yoMama01','mamaYo01'),
(7,'Rufus','Murdock','ruMo01','moRu01'),
(8,'Luke','Skywalker','lukeJedi01','jediLuke01')
SELECT ROW_NUMBER() OVER(ORDER BY EventValue) AS MetaID, *
FROM (
SELECT
t.EventValue
, MAX(CASE WHEN t.Person1 IN(p.DatabaseOneID, p.DatabaseTwoID) THEN p.ID ELSE NULL END) AS Person1ID
, MAX(CASE WHEN t.Person2 IN(p.DatabaseOneID, p.DatabaseTwoID) THEN p.ID ELSE NULL END) AS Person2ID
, MAX(CASE WHEN t.Person3 IN(p.DatabaseOneID, p.DatabaseTwoID) THEN p.ID ELSE NULL END) AS Person3ID
, MAX(CASE WHEN t.Person4 IN(p.DatabaseOneID, p.DatabaseTwoID) THEN p.ID ELSE NULL END) AS Person4ID
FROM #tb1 t
LEFT JOIN #Person p
ON p.DatabaseOneID IN(t.Person1, t.Person2, t.Person3, t.Person4)
OR p.DatabaseTwoID IN(t.Person1, t.Person2, t.Person3, t.Person4)
GROUP BY t.EventValue
) D
I currently have a Lookup Transform looking up the first Person column, but couldn't figure out how to convert all 4 Person columns into IDs within the same lookup.
You cannot do this within the same lookup, you have to add a Lookup Transformation for each Column. In your case you should add 4 Lookup Transformation.
If source database and destination database are on the same server, then you can use a SQL query to achieve that as mentioned in the other answer, but in case that each database is on a separate server you have to go with Lookup transformation or you have to import data into a staging table and perform Join operations using SQL.

Remove more than one space from table in SQL Server

TableA
id Name
--------------------------------
1 Ram Kumar
2 Rajesh A
3 Avinash K Bae
4 Kishore Babu
Try like below
Schema:
CREATE TABLE #TAB(id INT, Name VARCHAR(500))
INSERT INTO #TAB
SELECT 1, 'Ram Kumar'
UNION ALL
SELECT 2, 'Rajesh A'
UNION ALL
SELECT 3, 'Avinash K Bae'
UNION ALL
SELECT 4, 'Kishore Babu'
Now do the trick with Replace
SELECT ID
,REPLACE(REPLACE( REPLACE(Name,' ','><'), '<>',''),'><',' ')
FROM #TAB
Result:
+----+---------------+
| ID | NEW_NAME |
+----+---------------+
| 1 | Ram Kumar |
| 2 | Rajesh A |
| 3 | Avinash K Bae |
| 4 | Kishore Babu |
+----+---------------+

SQL Server : Insert statement duplicating non duplicate values

I have run into this scenario a couple of times, but it does not occur all the time on the same databases while testing. I have two separate databases I am merging into a single db both structured exactly the same. When inserting records from one database to the other, I am seeing distinct values duplicate on my target database however exist only once in one source and not in the target.
Example:
DB1..Customer
Cust_ID | Last_Name | First_Name | Phone | Email | Field1
1 | Smith | John | 111-1111 | m#M.com |
DB2..Customer
Cust_ID | Last_Name | First_Name | Phone | Email | Field1
1 | Jones | Steve | 222-2222 | S#S.com |
2 | Smith | Tom | 333-3333 | S#m.com |
When I run my query:
INSERT INTO DB1..Customer (Last_Name, First_Name, Phone, Email, Field1)
SELECT
Last_name, First_Name, Phone, Email, Cust_ID
FROM
DB2..Customer DB2
WHERE
DB2.Cust_ID NOT IN (SELECT DB2.Cust_ID
FROM DB2..Customer DB2
INNER JOIN DB1..Customer DB1 ON DB1.Last_Name = DB2.Last_Name
AND DB1.First_Name = DB2.First_Name
AND DB1.Email = DB2.Email)
Results:
DB1..Customer
Cust_ID | Last_Name | First_Name | Phone | Email | Field1
1 | Smith | John | 111-1111 | m#M.com |
2 | Jones | Steve | 222-2222 | S#S.com | 1
3 | Jones | Steve | 222-2222 | S#S.com | 1
4 | Jones | Steve | 222-2222 | S#S.com | 1
5 | Jones | Steve | 222-2222 | S#S.com | 1
6 | Smith | Tom | 333-3333 | S#m.com | 2
7 | Smith | Tom | 333-3333 | S#m.com | 2
8 | Smith | Tom | 333-3333 | S#m.com | 2
I notice duplicate values entered when I run a count on the field1 column having more than one count of db2..customer.cust_id. Since Cust_ID is the PK value I should only have one value flow into the field1 column per my query.
Any ideas or suggestions on why this may be occurring? My last run of my query duplicated some items up to 4 times. It seems to me SQL is caught in a bit of a loop searching for the patient while also writing them to the target db at the same time.
Left joining is a little slower, but easier to read and does what you want.
INSERT INTO DB1..Customer(
Last_Name
, First_Name
, Phone
, Email
, Field1)
SELECT
B.Last_name
, B.First_Name
, B.Phone
, B.Email
, B.Cust_ID
FROM
DB2..Customer B
LEFT JOIN
DB1..Customer A ON
A.Last_Name = B.Last_Name
AND
A.First_Name = B.First_Name
AND
A.Email = B.Email
AND
A.Phone = B.Phone
WHERE A.Cust_ID IS NULL;
Could you try changing the aliases used in the outer query and sub-query to be different? I don't have multiple instances at hand to test, but I wonder if it is being interpreted as a correlated subquery.
Try the following query, which uses DB1_Inner/DB2_Inner/DB2_Outer to differentiate the aliases:
Insert into DB1..Customer (Last_Name, First_Name, Phone, Email, Field1)
SELECT Last_name, First_Name, Phone, Email, Cust_ID
from DB2..Customer DB2_Outer
Where DB2_Outer.Cust_ID not in
(Select DB2_Inner.Cust_ID
from DB2..Customer DB2_Inner
Inner Join DB1..Customer DB1_Inner
on DB1_Inner.Last_Name=DB2_Inner.Last_Name
and DB1_Inner.First_Name=DB2_Inner.First_Name
and DB1_Inner.Email=DB2_Inner.Email)

SQL Server parent child (parent see all everything)?

This is my table:
EmployeeID Employee ManagerID
---------------------------------
1 Anna 5
2 John 4
3 Steve 4
4 Lisa 1
5 Adam NULL
6 Per 1
There is no problem for me to get parent and child relationship with a self-join like this:
SELECT
E.EmployeeID,
E.Employee AS Employee,
E.ManagerID,
M.Employee AS Manager
FROM
Employee AS E
LEFT JOIN
Employee AS M ON E.ManagerID = M.EmployeeID
EmployeeID Employee ManagerID Manager
1 Anna 5 Adam
2 John 4 Lisa
3 Steve 4 Lisa
4 Lisa 1 Anna
5 Adam NULL NULL
6 Per 1 Anna
However, How would i go about to make sure that the parent see the whole hierarchy level?
I would like the table to look like this:
EmployeeID Manager Employee EmployeeID
5 Adam Anna 1
5 Adam Per 6
5 Adam Lisa 4
5 Adam John 2
5 Adam Steve 3
1 Anna Per 6
1 Anna Lisa 4
1 Anna John 2
1 Anna Steve 3
4 Lisa John 2
4 Lisa Steve 3
Note: in this example i only have 3 levels of manger but there can be many more
You can try this:
DECLARE #DataSource TABLE
(
[EmployeeID] TINYINT
,[Employee] VARCHAR(12)
,[ManagerID] TINYINT
);
INSERT INTO #DataSource ([EmployeeID], [Employee], [ManagerID])
VALUES (1, 'Anna', 5)
,(2, 'John', 4)
,(3, 'Steve', 4)
,(4, 'Lisa', 1)
,(5, 'Adam', NULL)
,(6, 'Per', 1);
WITH DataSource AS
(
SELECT DISTINCT DS1.*
,0 AS [Level]
,DS1.[EmployeeID] AS Parent
FROM #DataSource DS1
INNER JOIN #DataSource DS2
ON DS1.[EmployeeID] = DS2.[ManagerID]
UNION ALL
SELECT DS2.*
,DS1.[Level] + 1
,DS1.Parent
FROM DataSource DS1
INNER JOIN #DataSource DS2
ON DS1.[EmployeeID] = DS2.[ManagerID]
)
SELECT DS1.[EmployeeID]
,DS1.[Employee] AS [Manager]
,DS.[EmployeeID]
,DS.[Employee]
FROM DataSource DS
INNER JOIN #DataSource DS1
ON DS.[Parent] = DS1.[EmployeeID]
WHERE DS.[Level] <> 0
ORDER BY DS.[Parent] DESC;
We are using recursive CTE and it may look a kind of messy and complicated if you are seeing this syntax for the first time, but it's nothing special.
When are using recursive CTE run some performance tests in order to be sure it is the right technique for solving your issue.
You should use recursive CTE syntax. In the first iteration (before UNION ALL) you get all Parent-Child pairs. In the recursive part (after UNION ALL) you get the next level child for each pair and substitute it into the pair Parent-Child instead of the Child leaving Parent the same.
WITH CTE AS
(
SELECT TP.EmployeeID as ManagerId,
TP.Employee as Manager,
TC.EmployeeID as EmployeeID,
TC.Employee as Employee
FROM TEmployee as TP
JOIN TEmployee as TC on (TP.EmployeeID = TC.ManagerID)
UNION ALL
SELECT TP.ManagerId as ManagerId,
TP.Manager as Manager,
TC.EmployeeID as EmployeeID,
TC.Employee as Employee
FROM CTE as TP
JOIN TEmployee as TC on (TP.EmployeeID = TC.ManagerID)
)
SELECT * FROM CTE Order By ManagerID
result:
+-----------+---------+------------+----------+
| ManagerId | Manager | EmployeeID | Employee |
+-----------+---------+------------+----------+
| 1 | Anna | 4 | Lisa |
| 1 | Anna | 6 | Per |
| 1 | Anna | 2 | John |
| 1 | Anna | 3 | Steve |
| 4 | Lisa | 2 | John |
| 4 | Lisa | 3 | Steve |
| 5 | Adam | 1 | Anna |
| 5 | Adam | 4 | Lisa |
| 5 | Adam | 6 | Per |
| 5 | Adam | 2 | John |
| 5 | Adam | 3 | Steve |
+-----------+---------+------------+----------+

Update second column into one

I would like to update multiple colums into one column of an another table:
I am using MS SQl Server
Table 1:
Num | ColumnA | ColumnB |
--------------------------
1 | Peter | Mueller |
1 | Jonny | Corleone |
2 | John | Cohn |
1 | Sarah | Wood |
Now I want to update ColumnA and ColumnB into ColumA of Table2 like this:
Table2:
Num | ColumnC |
----------------------------------------------------
1 | Peter, Mueller, Jonny, Corleone, Sarah, Wood |
2 | John, Cohn |
It is not good practice to store multiple values in a single column. If you need to do this though, then try this:
SELECT adress,
num,
Stuff((SELECT ',' + ColumnA + ',' + ColumnB
FROM table1 a
WHERE a.Num = b.Num
FOR xml path('')), 1, 1, '')
FROM table1 b
GROUP BY num

Resources