How to Mapping Columns in a Self-Join table! - sql

I have a parent/child table and want to update Its PK and FK to new values. the problem is that oldParent Ids Should Sync with new ones matching with Old Ids. so:
I have this data as a temp table:
OldID | OldParentID | NewID | NewParentID
1 0 10 NULL
2 0 11 NULL
3 2 13 NULL
4 3 14 NULL
and I Need Update NewParentID as Follows:
OldID | OldParentID | NewID | NewParentID
1 0 10 0
2 0 11 0
3 2 13 11
4 3 14 13

declare #T table
(
OldID int,
OldParentID int,
NewID int,
NewParentID int
)
insert into #T
select 1, 0, 10, null union all
select 2, 0, 11, null union all
select 3, 2, 13, null union all
select 4, 3, 14, null
update T1
set T1.NewParentID = coalesce(T2.NewID, 0)
from #T as T1
left outer join #T as T2
on T1.OldParentID = T2.OldID

Related

SQL for the below requirements

I am having trouble framing a SQL to get the desired outputs.
Table X
Id_X | GroupId | SomeColumn
Table R
Id_R | Id_X | GroupId | RColumn
The objective is to pick Id_X from Table R that have only GroupId values (A,B) and RColumn value is RValue
Ex:
Table X
1 | A | SomeValue
1 | B | SomeValue
2 | A | SomeValue
2 | B | SomeValue
2 | B | SomeValue
2 | C | SomeValue
Table R
101 | 1 | A | RValue
102 | 2 | A | RValue
The SQL should return 1
SELECT
[X].Id_X
FROM
[R]
INNER JOIN [X] ON
[R].Id_X = [X].Id_X
AND
[R].GroupId = [X].GroupId
WHERE
[X].GroupId IN ( 'A', 'B' )
AND
[R].RColumn = 'RValue'
If i understand correctly, your query should be
DECLARE #TableX AS TABLE
(
Id_X int, GroupId varchar(10), SomeColumn varchar(20)
)
INSERT INTO #TableX
VALUES
( 1, 'A', 'SomeValue'),
( 1, 'B', 'SomeValue'),
( 2, 'A', 'SomeValue'),
( 2, 'B', 'SomeValue'),
( 2, 'B', 'SomeValue'),
( 2, 'C', 'SomeValue')
DECLARE #TableR AS TABLE
(
ID_R int, Id_X int, GroupId varchar(10),RColumn varchar(10)
)
INSERT INTO #TableR
VALUES (101,1,'A','RValue'), (102,2,'A','RValue')
SELECT DISTINCT tr.Id_X
FROM #TableR tr
INNER JOIN #TableX tx ON tx.Id_X = tr.Id_X AND tx.GroupId = tr.GroupId
WHERE tr.RColumn = 'RValue'
AND NOT EXISTS ( SELECT 1 FROM #TableX tx2
WHERE tx2.Id_X = tx.Id_X
AND tx2.GroupId NOT IN ('A','B')
)
Demo link: http://rextester.com/EGLOT75874

T-SQL results in to columns

I have a table (t1) like below
Id Name RelId
1 a 2
2 b 3
3 c 4
4 d 3
5 e 6
The other table (t2)
Id data FK Order
1 aa 2 2
2 bb 2 3
3 cc 2 1
4 dd 2 4
5 ee 2 5
6 ff 3 3
7 gg 3 2
8 hh 3 1
9 ii 4 7
10 jj 4 4
11 kk 4 1
12 ll 4 3
13 mm 6 1
14 nn 6 2
15 oo 6 3
16 pp 6 4
My output result am looking for is
+----+------+-------+-------+------+----------+
| id | name | RelId | Col 1 | Col2 | Col-Oth |
+----+------+-------+-------+------+----------+
| 1 | a | 2 | cc | aa | bb,dd,ee |
| 2 | b | 3 | hh | gg | ff |
| 3 | c | 4 | kk | ll | jj,ii |
| 4 | d | 3 | hh | gg | ff |
| 5 | e | 6 | mm | nn | oo,pp |
+----+------+-------+-------+------+----------+
based on the Relid in T1 table join with FK column in T2 and populate col1 with the least order data, col2 with the next higher order data and col-oth with remaining data comma separated ordered.
Need your help on same.
SELECT id,name,RelId, (select data,rownumber() (partition by data order by order asc) from t2 inner join t1 on t1.relid= t2.FK) from t1
Try following query:
DECLARE #TEMP TABLE
(
Id INT,
Name VARCHAR(10),
RelId INT
)
INSERT INTO #TEMP VALUES (1,'a',2),(2,'b',3),(3,'c',4),(4,'d',3),(5,'e',6)
DECLARE #TEMP1 TABLE
(
Id INT,
Data varchar(10),
FK INT,
[order] INT
)
INSERT INTO #TEMP1 VALUES
(1 ,'aa',2,2),(2 ,'bb',2,3),(3 ,'cc',2,1),(4 ,'dd',2,4),(5 ,'ee',2,5),
(6 ,'ff',3,3),(7 ,'gg',3,2),(8 ,'hh',3,1),(9 ,'ii',4,7),(10,'jj',4,4),
(11,'kk',4,1),(12,'ll',4,3),(13,'mm',6,1),(14,'nn',6,2),(15,'oo',6,3),(16,'pp',6,4)
SELECT
t1.*,
(SELECT Data FROM (SELECT ROW_NUMBER() OVER(ORDER BY t2.[order]) As RowNo,Data FROM #TEMP1 t2 WHERE t2.FK = t1.RelId)t3 WHERE t3.RowNo=1),
(SELECT Data FROM (SELECT ROW_NUMBER() OVER(ORDER BY t2.[order]) As RowNo,Data FROM #TEMP1 t2 WHERE t2.FK = t1.RelId)t3 WHERE t3.RowNo=2),
STUFF((SELECT DISTINCT ',' + Data FROM (SELECT ROW_NUMBER() OVER(ORDER BY t2.[order]) As RowNo,Data FROM #TEMP1 t2 WHERE t2.FK = t1.RelId)t3 WHERE t3.RowNo > 2 FOR XML PATH ('')), 1, 1, '')
FROM
#TEMP t1
Using PIVOT:
DECLARE #t1 TABLE
(
ID INT ,
Name CHAR(1) ,
RelID INT
)
DECLARE #t2 TABLE
(
ID INT ,
Data CHAR(2) ,
RelID INT ,
Ordering INT
)
INSERT INTO #t1
VALUES ( 1, 'a', 2 ),
( 2, 'b', 3 ),
( 3, 'c', 4 ),
( 4, 'd', 3 ),
( 5, 'e', 6 )
INSERT INTO #t2
VALUES ( 1, 'aa', 2, 2 ),
( 2, 'bb', 2, 3 ),
( 3, 'cc', 2, 1 ),
( 4, 'dd', 2, 4 ),
( 5, 'ee', 2, 5 ),
( 6, 'ff', 3, 3 ),
( 7, 'gg', 3, 2 ),
( 8, 'hh', 3, 1 ),
( 9, 'ii', 4, 7 ),
( 10, 'jj', 4, 4 ),
( 11, 'kk', 4, 1 ),
( 12, 'll', 4, 3 ),
( 13, 'mm', 6, 1 ),
( 14, 'nn', 6, 2 ),
( 15, 'oo', 6, 3 ),
( 16, 'pp', 6, 4 );
WITH cte1
AS ( SELECT t1.ID ,
t1.Name ,
t1.RelID ,
t2.Data ,
ROW_NUMBER() OVER ( PARTITION BY t1.ID ORDER BY t2.Ordering ) AS rn
FROM #t1 t1
JOIN #t2 t2 ON t1.RelID = t2.RelID
),
cte2
AS ( SELECT ID ,
Name ,
RelID ,
Data ,
rn ,
STUFF(( SELECT ',' + Data
FROM cte1 ci
WHERE co.ID = ci.ID
AND rn > 2
FOR
XML PATH('')
), 1, 1, '') AS Col3
FROM cte1 co
)
SELECT ID ,
Name ,
RelID ,
[1] AS Col1 ,
[2] AS Col2 ,
Col3
FROM cte2 PIVOT( MAX(data) FOR rn IN ( [1], [2] ) ) p
Output:
ID Name RelID Col1 Col2 Col3
1 a 2 cc aa bb,dd,ee
2 b 3 hh gg ff
3 c 4 kk ll jj,ii
4 d 3 hh gg ff
5 e 6 mm nn oo,pp
Execution plan of my statement
Execution plan of accepted statement:
Which is better? :)

Selecting all parents in the order of relation from hierarchical table SQL

I've a table like this with a parent child relation in the same table
AccountID| ParentID | AccountName
----------------------------------------------
1 | 0 | Root
2 | 1 | Child1
3 | 1 | Child2
4 | 2 | Child3
5 | 4 | Child1
6 | 5 | Child1
7 | 6 | Child1
8 | 6 | Child1
So when I send the account ID 7 I have to get the tables in the order like child,father,grandfather.. that way.. So for 7, I need to get all parets like this
AccountID
---------
7
6
5
4
2
1
So the most important point is the order. It should be from the bottom level to its next higher then to the next...
You can use a recursive CTE:
declare #childAccID int
set #childAccID = 7
;WITH Rec_CTE
AS(
SELECT 1 AS Level,
tChild.*
FROM dbo.TableName tChild
WHERE tChild.AccountID = #childAccID
UNION ALL
SELECT Level + 1 AS Level,
parent.*
FROM Rec_CTE tParent
INNER JOIN dbo.TableName parent
ON parent.AccountID = tParent.ParentID
)
SELECT * FROM Rec_CTE
ORDER BY Level
DEMO
Try this:
create table DemoTable
(
accountid bigint
,parentid bigint
,accountname nvarchar(128)
)
insert DemoTable(accountid,parentid,accountname)
select 1, null, 'Root'
union select 2, 1, 'Child1'
union select 3, 1, 'Child2'
union select 4, 1, 'Child3'
union select 5, 2, 'Child1.1'
union select 6, 2, 'Child1.2'
go
declare #findMe bigint = 6;
with myCTE as
(
select accountid,parentid,accountname,1 hierarchyLevel
from DemoTable
where accountid = #findMe
union all
select b.accountid,b.parentid,b.accountname, a.hierarchyLevel + 1
from myCTE a
inner join DemoTable b
on b.accountid = a.parentid
)
select * from myCTE
order by hierarchyLevel

Selecting children from an infinite hierarchy

I have an SQL table like this
ID | ParentID
1 | null
2 | null
3 | null
4 | 1
5 | 4
6 | 5
7 | 6
8 | 7
9 | 8
Now, as you can see, a child parent relationship is maintained. I want a query to select "all level" children of a given ID.
Suppose if I input ID = 1, the result should be
ID | ParentID
1 | null
4 | 1
5 | 4
6 | 5
7 | 6
8 | 7
9 | 8
So all immediate children, as well as children of their children at any level, should come up.
Is it possible to do this in MS SQL server? I have MS-SQL server 2012.
Here is an example with an extra field Name, but with CTE the recursion is simple:
DECLARE #ID int
SET #ID = 1;
WITH CTE_Table_1
(
ID,
Name,
ParentID,
TreeLevel
)
AS(
SELECT
ID,
Name,
ParentID,
0 AS TreeLevel
FROM Table_1
WHERE ID = #ID
UNION ALL
SELECT
T.ID,
T.Name,
T.ParentID,
TreeLevel + 1
FROM Table_1 T
INNER JOIN CTE_Table_1 ON CTE_Table_1.ID = T.ParentID
)
SELECT * FROM CTE_Table_1
Try this workin fine : http://www.sqlteam.com/Forums/topic.asp?TOPIC_ID=101053
-- Structure
create table dbo.MyPeople (Id int, Name varchar(30), ParentId int)
-- Data
insert dbo.MyPeople
select 1, 'P1', null
union all select 2, 'P2', null
union all select 3, 'P1C1', 1
union all select 4, 'P1C2', 1
union all select 5, 'P2C1', 2
union all select 6, 'P1C2C1', 4
union all select 7, 'P1C1C1', 3
union all select 8, 'P1C1C1C1', 7
union all select 9, 'P2C1C1', 5
union all select 10, 'P1C3', 1
go
-- Function
create function dbo.AncestorPath(#Id int) returns varchar(100) as
begin
declare #Path varchar(100)
while 0 = 0
begin
select #Path = cast(Id as varchar(5)) + isnull('/' + #Path, ''), #Id = ParentId
from dbo.MyPeople where Id = #Id
if ##rowcount = 0 break
end
return #Path
end
go
-- Calculation
select * from (
select *, dbo.AncestorPath(Id) as AncestorPath from dbo.MyPeople) a
where '/' + AncestorPath + '/' like '%/1/%'
or
Try recursive procedure like this
ALTER PROCEDURE dbo.GetChildren
#ParentId int
AS
SET NOCOUNT ON
SELECT *
FROM MainTable
WHERE ChildId IN
(
SELECT ParentId
FROM f_GetChildren(#ParentId)
UNION
SELECT ChildId
FROM f_GetChildren(#ParentId)
)
ORDER BY ParentId
SET NOCOUNT OFF
RETURN
From SQL Server 2005, Common Table Expressions have been added to T-SQL of SQL Server that help you in this kind of hierarchial queries. That's what you are looking for!

problem in writing a sql query

Getting a problem in writing an sql query.
two tables:
1st: created patient table 2nd: already created doc table
patientid patientname docid workstatus docid docname
1 aaa 2 10 1 ggg
2 bbb 2 20 2 hhh
3 ccc 1 10 3 iii
4 ddd 3 10
5 eee 3 20
6 fff 2 10
expected output:
docname workstatus(10) workstatus(20)
ggg 1 0
hhh 2 1
iii 1 1
can also use temporary tables between the queries
Thanks in advance
Try this
Full working example
declare #patient as table(
patientID int IDENTITY(1,1) NOT NULL,
patientName varchar(25),
docID int,
workstatus smallint
)
declare #doc as table(
docID int IDENTITY(1,1) NOT NULL,
docname varchar(25)
)
insert into #patient
select 'aaa', 2, 10
union all
select 'bbb', 2, 20
union all
select 'ccc', 1, 10
union all
select 'ddd', 3, 10
union all
select 'eee', 3, 20
union all
select 'fff', 2, 10
insert into #doc
select 'ggg'
union all
select 'hhh'
union all
select 'iii'
select docname,
SUM(case when t1.workstatus = 10 THEN 1 ELSE 0 END) as [workstatus(10)],
SUM(case when t1.workstatus = 20 THEN 1 ELSE 0 END) as [workstatus(20)]
from #patient t1
inner join #doc t2 on t1.docid=t2.docid
GROUP BY docname
Select d.docname,
SUM(case when c.workstatus = 10 THEN 1 ELSE 0 END) as [WorkStatus(10)],
SUM(case when c.workstatus = 20 THEN 1 ELSE 0 END) as [WorkStatus(20)]
from created_patient_table c
inner join already_created_doc_table d on c.docid=d.docid
group by d.docid,d.docname