How to form Management Hierarchy Formation in SQL Server? - sql

how to form the management hierarchy for below records?
Input Data:
Id
Sub ID
Name
Description
101
NULL
Page Reference
Page Reference
102
1
Page 1
Page 1
103
2
Ashok
Ashok
104
3
Kumar
Kumar
105
4
Page 2
Page 2
106
5
Arvind
Arvind
107
4
Page 11
Page 11
108
6
Gova
Gova
109
7
Gokul
Gokul
110
8
Kannan
Kannan
I tried with Recursion CTE, I am not able to find exact solution. Need an below format,
Conditions are
New Leaf ID --> If Sub ID IS NULL , then it will be 1 , If contains page row, it will be 2, if contains other than that it will be 3.
Page --> Whenever Page row starts, from the next row original information showing for that page. we need to form based on the lead rows.
Output Data:
Id
Sub ID
Name
Page
New Leaf ID
101
NULL
Page Reference
1
102
1
Page 1
Page 1
2
103
2
Ashok
Page 1
3
104
3
Kumar
Page 1
3
107
4
Page 11
Page 11
2
108
6
Gova
Page 11
3
109
7
Gokul
Page 11
3
110
8
Kannan
Page 11
3
105
4
Page 2
Page 2
2
106
5
Arvind
Page 2
3

The new leaf id is conditional logic. As for the page, it is a bit trickier: it seems like the ordering of the rows defines the dependencies, so basically you want to relate each level 3 leaf to the preceding level 2.
Here is an approach using a window count to identify leafs that belong to the same page:
select id, subid, name,
case when sub_id is not null
then max(case when name like 'Page %' then name end) over(order by id)
end as page,
case
when subid is null then 1
when name like 'Page %' then 2
else 3
end as new_leaf_id
from (
select t.*,
sum(case when name like 'Page %' then 1 else 0 end) over(order by id) grp
from mytable t
) t

Related

Is it allowed to have multiple empty parentid's?

So first I have a typical table that looks like this:
SectionID
SectionName
DivisionID
DivisionName
IndustryID
IndustryName
SectorID1
SecNam1
DivisionID11
DivName11
IndustryID111
InduNam111
SectorID1
SecNam1
DivisionID11
DivName11
IndustryID112
InduNam112
SectorID1
SecNam1
DivisionID12
DivName12
IndustryID121
InduNam121
SectorID2
SecNam2
DivisionID21
DivName21
IndustryID211
InduNam211
SectorID3
SecNam3
DivisionID31
DivName31
IndustryID311
InduNam311
now I want to transform it in a more dynamic hierarchy structure with parentIds which looks like this:
ID
ParentID
Level
Type
Name
1
NULL
1
SectorID1
SecNam1
2
NULL
1
SectorID2
SecNam2
3
NULL
2
SectorID3
SecNam3
4
1
2
DivisionID11
DivName11
5
1
2
DivisionID12
DivName12
5
1
2
DivisionID21
DivName21
6
2
2
DivisionID31
DivName31
7
2
3
IndustryID
InduNam111
8
2
3
IndustryID
InduNam112
9
2
3
IndustryID
InduNam121
10
2
3
IndustryID
InduNam211
11
2
3
IndustryID
InduNam311
Is it okay to have multiple empty parentId's?
Is this transformation ok?
Having the parent for the root node as null is fine - though in some designs this is populated with the same value as the record itself rather than having to deal with nulls e.g.
ID
ParentID
Level
Type
Name
1
SecNam1
1
SectorID1
SecNam1
Also, having different versions of the same value in the TYPE column looks odd. I would have expected just "SectorID" not "SectorID1", "SectorID2", "SectorID3". The difference between different sectors is handled by the name of the sector e.g. like you have done with "Division".
Did you mean the level of "SectorID3" to be 2 rather than 1 - or is that just a typo?

SQL server create how to create a new column based on previous row condition

I'm trying to create a new column, whose values are dependent to the previous index row values, like in the example below:
Index
ID
AGE
SEX
HireMonth
Tag
1
101
23
M
9
101
2
102
32
M
12
102
3
103
25
F
11
1
4
104
29
M
10
104
5
105
45
F
1
1
6
106
21
M
7
106
7
107
56
F
6
107
8
108
12
M
4
108
Here's how I'm creating the Tag column :
CASE WHEN AGE > 25 AND HireMonth => 9
THEN (next row value = 1 AND same row ID )
ELSE ID
END AS Tag
Have you tried:
select [Index], ID, AGE, SEX, HireMonth,
CASE WHEN LAG(AGE, 1) OVER (ORDER BY [Index]) > 25 AND LAG(HireMonth, 1) OVER (ORDER BY [Index]) >= 9
THEN 1
ELSE ID
END AS Tag
FROM SOME_TABLE

How to select faulty records?

I'm investigating an error in one of our tables of a geographical database. Given the table below, the DistrictName and DisId should always have the same combination (i.e. Bronx = 11, Manhatten = 14), but some records have a different DisId (while still sharing the the same DistrictName).
Id DistrictName DisId Section
------------------------------------------------
1 Bronx 11 1
2 Bronx 11 2
3 Brooklyn 12 1
4 Brooklyn 13 2 //wrong
5 Manhatten 14 1
6 Manhatten 14 2
7 Queens 15 1
8 Queens 16 2 //wrong
9 Queens 17 3 //wrong
How can I select all faulty records in a query?
There is always a Section 1, so records with a section > 1 containing the same DistrictName but having a deviating DisId are the ones I'm looking for.
I've tried using a group by (districtname) but I'm having difficulties comparing with the section1 record. I'm kind of lost when it comes to putting the logic in the having or where clause. Any help appreciated!
select * from your_table
where section > 1
and districtname in
(
select districtname
from your_table
group by districtname
having count(distinct disid) > 1
)

Microsoft SQL - Remove duplicate data from query results

I am new to SQL Server and need help with one of my SQL query.
I have 2 tables (Rating and LikeDislike).
I am trying to get data from both of these tables using a LEFT JOIN like this:
SELECT distinct LD.TopicID, R.ID, R.Topic, R.CountLikes, R.CountDisLikes, LD.UserName, LD.Clikes
FROM Rating As R
LEFT JOIN LikeDislike AS LD on LD.TopicID = R.ID
The above SELECT statement displays results fine but also includes duplicates. I want to remove duplicates when the data is displayed, I tried using DISTINCT and GROUP BY, but with no luck, maybe because I am not using it correctly.
To be more clear and less confusing let me tell you what exactly each table does and what I am trying to achieve.
The Rating table has following columns (ID, Topic, CountLikes, CountDisLikes, Extra, CreatedByUser). It stores topic information and number of likes and dislikes for each topics and the UserID of the user who created that topic.
Rating table with sample data
ID Topic CountLikes CountDisLikes Extra CreatedByUser
1 Do You Like This 211 58 YesId 2
2 Or This 17 25 This also 3
79 Testing at home 1 0 Testing at home 2
80 Testing at home again 1 0 Testing 2
82 testing dislikes 0 1 Testing 2
76 Testing part 3 7 5 Testing 3 4
77 Testing part 4 16 6 Testing 4 5
The LikeDisLike table has following columns (ID, TopicID, UserName, Clikes). TopicID is a FK to the ID column in Rating table.
LikeDislike table with sample data
ID TopicID UserName Clikes
213 77 2 TRUE
214 76 2 FALSE
215 77 5 TRUE
194 77 3 TRUE
195 76 3 FALSE
196 2 3 TRUE
197 1 3 FALSE
Now what I am trying to do is get information from both of this table without duplicate rows. I need to get data all the columns from Rating table + UserName and Clikes columns from LikeDislike table without any duplicate rows
Below are the results with duplicates
TopicID ID Topic CountLikes CountDislikes UserName Clikes
NULL 79 Testing at home 1 0 NULL NULL
NULL 80 Testing at home2 1 0 NULL NULL
NULL 82 testing dislikes 0 1 NULL NULL
1 1 Do You Like This 211 58 3 FALSE
2 2 Or This 17 25 3 TRUE
76 76 Testing part 3 7 5 2 FALSE
76 76 Testing part 3 7 5 3 FALSE
77 77 Testing part 4 16 6 2 TRUE
77 77 Testing part 4 16 6 3 TRUE
77 77 Testing part 4 16 6 5 TRUE
Just like in yesterday's post, I don't think you understand what DISTINCT is suppose to return you. Because you have different values in your LikeDislike table, you are returning the DISTINCT rows.
Let's take TopicId 77 for instance. It returns 3 DISTINCT rows because you have 3 matching records in your LikeDislike table. If your desired output is a single row where the UserName and Clikes are comma delimted, that is possible -- look into using for xml and perhaps stuff (here is a recent answer on the subject). Or if you want to return the first row that matches the TopicId, then that is possible as well -- look into using a subquery with row_number.
Please let us know your desired output and we can help provide a solution.
Good luck.

Picking from Custom Priority SQL query

I have a recordset that looks something like this
Tradeid CUstom Priority
101 4
101 2
101 3
102 6
102 1
102 5
I have got my records sorted in custom order of priority 4,2,3,8,5,9,10,1,6,7,11
What i now want is just the first records of each group
As in the above record set should get filtered to
101 4
102 6
Rember, you cant apply max or min on custom priority coz it could appear in any form
as 1,5 or 4,2
how would you do this....
Note:
This is the way i have done the ordering
ORDER BY
CASE CRL.CONFIRM_SOURCE_ID
WHEN 4 THEN 1
WHEN 2 THEN 2
WHEN 3 THEN 3
WHEN 8 THEN 4
WHEN 5 THEN 5
WHEN 9 THEN 6
WHEN 10 THEN 7
WHEN 1 THEN 8
WHEN 6 THEN 9
WHEN 7 THEN 10
WHEN 11 THEN 11
WHEN NULL THEN 12
END
It looks like you want the MAX Custom Priority for each Tradeid.
SELECT TradeId, MAX([Custom Priority]) AS MaxCustomPriority
FROM YourTable
GROUP BY TradeId