Parent-child relation entity to MAP to view model - c#

I have location data coming from DB. There is parent-Child Relationship in my Location table.
I retrieved the records. But problem is how can I populate my View Model.
For example
Location 'US' has child 'California' and 'New York', and they have their own child.
I am not using any mapping tool.
Here is the sample data
Id ChildId Name
1 null US
2 null Canada
3 1 California
4 3 Los Angeles
5 2 Nova Scotia
6 5 Halifax
And I dont know the depth of my Location table's parent-Child relation ship
I like some solution so when I write
List<LocVM> obj=context.locations.select(w=new LocVM{....,ChileLocation=w.ChildLoc}).tolist();
so my object will have all locations and child locations
View Model
Class LocVM{
public int Id{get;set;}
public int chileId {get;set;}
public LocVM ChildLocations {get;set;}
}
So with query above
Any idea is welcome

Sample Data
IF OBJECT_ID('dbo.SampleData') IS NOT NULL
DROP TABLE SampleData
CREATE TABLE SampleData (ID int,ChildId INT,Name VARCHAR(20))
INSERT INTO SampleData
SELECT 1,null,'US' UNION ALL
SELECT 2,null,'Canada' UNION ALL
SELECT 3,1 ,'California' UNION ALL
SELECT 4,3 ,'Los Angeles' UNION ALL
SELECT 5,2 ,'Nova Scotia' UNION ALL
SELECT 6,5 ,'Halifax'
SELECT * FROM SampleData
This Recursive CTE May be able to solve your requirement.
;With Cte
AS
(
SELECT
ID
,ChildId
,CAST('/'+Name AS nvarchar(1000)) AS [Heirarchy]
FROM SampleData
WHERE ChildId IS NULL
UNION ALL
SELECT
e.ID
,e.ChildId
,CAST([Heirarchy]+'/'+e.Name AS nvarchar(1000)) AS [Heirarchy]
FROM SampleData e
INNER JOIN Cte t
ON t.ID = e.ChildId
)
SELECT ID
,RIGHT([Heirarchy],LEN([Heirarchy])-1) AS [CityHeirarchyPath]
FROM Cte
Result
ID CityHeirarchyPath
----------------------
1 US
2 Canada
5 Canada/Nova Scotia
6 Canada/Nova Scotia/Halifax
3 US/California
4 US/California/Los Angeles

Related

SQL get Distinct rows from joined tables

I'm trying to determine the following from the joining of two tables:
Sample TableA: Contains 1 column consisting of unique IDs
ID Name Department
1 John IT
2 Jason Sales
3 Dany IT
4 Mike HR
5 Alex HR
Sample TableB: Contains multiple columns, including ID from TableA. For example:
ID AccountNumber WebID
1 10725 ABC1
1 10726 ABC1
1 10727 ABC1
2 20100 ABC2
2 20101 ABC2
3 30100 ABC3
4 40100 NULL
I want to get the following results:
ID Name WebID
1 John ABC1
2 Jason ABC2
3 Dany ABC3
4 Mike NULL
5 Alex NULL
I tried the following query, which is returning the correct rows for these sample tables:
Select count(a.ID), a.ID, a.Name, b.WebID from TableA a
left join TableB b on a.ID = b.ID
group by a.ID, a.Name, b.WebID
But my Actual Database tables, this query does not return correct number of rows: (30992)
TableA contains 29066 rows and TableB contains 23033 rows
The query should return 29066 rows, as it is Left Join.
When I checked the IDs that are in TableA, but not in TableB, there were 6033 rows:
Select * from TableA where ID not in (Select ID from TableB)
Am I missing something in the query?
TABLE B has duplicates of the ID column... the code below should work (but might not be the results you expect since I just do a max on the webid column which is fine if it is always the same but I need a rule if not)
I just saw you had a count... I added that in.
SELECT A.ID, A.Name, B.WebID
FROM TABLEA A
LEFT JOIN (
SELECT ID, MAX(WebID) AS WebID, count(*) as CNT
FROM TABLEB
GROUP BY ID
) B ON A.ID = B.ID
I think your query is as simple as that:
select a.ID,a.Name,b.WebID
from TableA a
left join TableB b on a.ID = b.ID

How to do hierarchical child count for a set of IDs in PostgreSQL (not a single ID)

I am using this SQL to retrieve hierarchical children count for a comment:
WITH RECURSIVE c AS (
SELECT "Id", "ParentId"
FROM public."Comments"
WHERE "ParentId" = #CommentId
UNION
SELECT s."Id", e."ParentId"
FROM public."Comments" e
INNER JOIN c s ON s."Id" = e."ParentId"
) SELECT COUNT(*)
FROM c;
It works as expected.
But how can I transform this SQL to work with a list of IDs, so it returns a dictionary where KEY is an ID from list in parameters and VALUE is a hierarchical count of children?
I am using this SQL with Dapper in C#
Sample "comments" table:
id | parentId
---------------
1 | null
2 | 1
3 | 2
4 | null
5 | 4
6 | 5
7 | 5
Input:
Array of IDs given to DB
[1, 4]
Output:
Dictionary which has ID from input as key and hierarchical children count as value
{1: 2, 4: 3}
P.S.: the code in input and output is just pseudocode
You can use this query to get the result set
WITH RECURSIVE c AS (
SELECT id, parentId, parentid as sid
FROM Comments
WHERE parentId = ANY(Array [1, 4])
UNION ALL
SELECT e.id, e.parentId, s.sid
FROM Comments e
INNER JOIN c s ON s.id = e.parentId
)
SELECT sid, COUNT(*)
FROM c
group by sid;
returns
sid count
4 3
1 2

Linq - select N-level childs from hierarchy parents

I have 2 tables as below:
Parent child relationship (table 1):
SourceId SourceParentId
1 null
2 1
3 2
4 null
Items (Table 2):
Id SourceId
1 1
2 1
3 2
4 2
5 3
6 4
How to write a linq query that return me all items based on Source ID? If my input is SourceId = 1, i will get items 1,2,3,4 & 5. If my input for sourceId is 2, i will get 3 items: 3, 4 & 5. If my input for sourceID is 4, it will return me item 6. My parent child is N-level and items can appear at any level.
Help :(
Here try this
--Variable to hold input value
DECLARE #inputSourceID INT = 1;
--Recursive CTE that finds all children of input SourceID
WITH MyCTE
AS
(
SELECT SourceID,
SourceParentID
FROM table1
WHERE SourceID = #inputSourceID
UNION ALL
SELECT table1.SourceID,
table1.SourceParentID
FROM table1
INNER JOIN MyCTE
ON table1.SourceParentID = MyCTE.SourceID
)
--Join the CTE with the table2 to find all id
SELECT table2.ID
FROM MyCTE
INNER JOIN table2
ON MyCTE.SourceID = table2.SourceID

Selecting Data from another table SQL Select Query

Here is 2 Tables that are joined by the StaffID
Job Table
=========
JobID AssignedTo(StaffID) Created By(StaffID)
1 2 1
2 3 2
Staff Table
============
StaffID Name
1 May
2 Bob
3 Mary
I need An SQL Statement to get the job details with the corresponding staff name but have problems doing so as i'm unable to differentiate the columns as they are using the same table. The end result should look like this
JobID Assigned To Created By
1 Bob May
2 Mary Bob
You need to join Staff table twice
select J.JobId, S1.Name AS AssignedTo, S2.Name AS CreatedBy
from Job J
inner join Staff S1 on S1.StaffID = J.AssignedTo
inner join Staff S2 on S2.StaffID = J.CreatedBy

TSQL Query Where All Records Must Exists to Return A Record

I am not sure even how to ask this question.
I have a table of tags:
TagId Tag
----- -----
1 Fruit
2 Meat
3 Grain
I have a table of events:
EventId Event
------- -----------
1 Eating Food
2 Buying Food
What I need to do is bring back only Events that have all selected tags associated with it.
If three tags are selected then only show event that have all three.
For example:
Mapping Table
EventId TagId
------- -----
1 1
1 3
2 1
If I write a query like this:
select * from MapTable where where tagId in (1,3)
This will return Eating Food and Buying Food.
But what I need to do is bring back events that have both tags 1 and 3. This means that the only event in this case I would return would be Eating Food as it has both selected tags.
I was wondering if this can be done in TSQL or if I will have to use the business layer to translate it into the object to return back to the GUI.
Thanks.
There was a very similar question yesterday: Query for exact match of users in a conversation in SQL Server
basically you can do this:
DECLARE #NumTags INT = 2
SELECT EventID
FROM EventTag
GROUP BY EventID
HAVING
Sum(CASE WHEN TagID IN (1, 3) THEN 1 ELSE 0 END) >= #NumTags
so this will find all events that both the tags exist in (this allows for instances where those two tags exist along with any additional tags)
Here is a solution for when you do not know the tags before hand.
Load the tags into a table variable and get the total count:
select #iCount = COUNT(*) from #Tags;
Then write your normal query and slam those results into a table variable:
insert into #EventTags(IsSet, EventId)
select distinct CASE WHEN TagID IN (select ID from #Tags) THEN 1 ELSE 0 END,
e.EventId
from Event_Tag e
inner join #Tags t on t.ID = e.TagId
Then to get back only Events that have ALL matching tags, not just ones that are in the selection, but ALL you do this:
select *
from Event_Tag e
inner join #Tags t on t.ID = e.TagId
where e.EventId in
( select EventId
from #EventTags
group by EventId
having count(EventId) = #iCount
)
Only bring back tags that have all tags associated.
Thank you again everyone for the ideas! Greatly appreciated all the feedback!
There's probably a better way to write it but this will give you what you are looking for:
select *
from event e
where exists(select * from maptable where eventid = e.eventid and tagid = 1) and exists(select * from maptable where eventid = e.eventid and tagid = 3)
You'll want to inner join the two tables, as follows
SELECT * FROM Events INNER JOIN MapTable ON MapTable.EventId=Events.EventID WHERE MapTable.TagID=1 AND MapTable.TagID=3

Categories