Run/Convert raw SQL Hierachy using/to Linq? - c#

I have the following query that works fine (ms-sql db), but cannot figure out how to run it using a Linq query. Also I could run it directly in Linq but have no idea in how to convert it to a Linq expression. Im trying to get all the subordinates for a employee all the way down the management tree. The table (in brief) is set up like this:
Emp_ID => Guid,
Reports_To => Guid, (The Emp_ID of their manager)
Name_Last, Name_First, etc.....
with Hierachy(Emp_ID, Reports_To, Name, Level)
as
(
select Emp_ID, Reports_To, Name_Last, 0 as Level
from Employees c
where c.Emp_ID = '5287E80D-8169-4D24-BABD-7639B1D68D59' ***This should also be a parameter, hard coded here**
union all
select c.Emp_ID, c.Reports_To, c.Name_Last, ch.Level + 1
from Employees c
inner join Hierachy ch
on c.Reports_To = ch.Emp_ID
)
select Emp_ID, Reports_To, Name
from Hierachy
where Level > 0
Thanks!

Related

SQL Query: Display only latest Id from each set

I have the following SQL Table:
Name Description Id UserId CreatedDate
UserSet1 Desc1 1 Abc 06/01/2018
UserSet1 Desc2 2 Def 06/02/2018
UserSet2 Desc for 2 5 NewUser 06/04/2018
UserSet2 Desc for 2 7 NewUser 06/19/2018
What I want to extract from the above table is just the latest Id for each Name so that I could get the following output
Name Description Id UserId CreatedDate
UserSet1 Desc2 2 Def 06/01/2018
UserSet2 Desc for 2 7 NewUser 06/19/2018
Since Id 2 & 7 are the latest entries in the table for UserSet1 & UserSet2, I would like to display that instead of all the entries in the table.
Any inputs how can I get the desired result.
I am open for solutions directly returning the output or any linq (C#) solutions as well. Ie returning the entire dataset and then using linq to filter the above.
EDIT: Since you are looking for the highest number ID, the GROUP BY method would probably be easier to work with.
Using a window function:
SELECT *
FROM (
SELECT Name, Description, Id, UserId, CreatedDate
, ROW_NUMBER() OVER (PARTITION BY Name ORDER BY CreatedDate DESC) AS rn
FROM myTable
) s1
WHERE rn = 1
I don't have an instance of dynamoDB to test on, but I believe it can use the ROW_NUMBER() window function.
Thanks everyone for pointing to right direction. I have got this working with the below code of Linq and C#:
var results = response.GroupBy(row => row.Name)
.SelectMany(g => g.OrderByDescending(row => row.Id).Take(1));
For the initial tests this seems to be working. Let me know if you think this has come issues.
This should be a general SQL answer:
SELECT * FROM yourtable Y1
WHERE Id = (SELECT MAX(Id)
FROM yourtable Y2
WHERE Y2.Name = Y1.Name)
If it was MS SQL you could use Partition By command, otherwise most performant way would be:
select * from Table
where Id in (
select Max(Id) from Table
Group By Name
)
not sure if you can leave Name out of the Select statement, you might need to do:
select * from Table
where Id in (
Select Id from
(select Name, Max(Id) as Id from Table
Group By Name)
)

SQL Server - Reuse previous query - similar logic to Linq

I am trying to write to achieve the logic of the following query:
select ......
from (select ..... from ... complex and long query #1) R1
(select ..... from ... complex and long query #2) R2
Where
NOT ( #DateStart > R2.IstEnde OR #DateEnd <= R2.IstStart)
OR
(
(select count(*)
from R2 // <---- BUG IS HERE
Where R2.IsOutsideTaskTimeFrame = 1 AND R2.IsManuallyFixed = 1
) > 0
)
order BY R2.PersonName, R1.YearOfWeek, R1.Week
Which obvious do not work because I am trying to "Reuse" the R2 in the "count()" where condition.
I am writing this based on the ".NET Linq" logic where we can "reuse" the previous query.
Can I even write this logic of "reusing" the previous query and not repeating it again?
Maybe you are looking for CTE - Common Table Expression:
;WITH R1 AS
(SELECT ...)
,R2 AS
(SELECT ...)
SELECT * FROM R1
... use R1 and R2 like any other table here (it's called "derived table")
If you need the result within independant queries, you might fill a declared table variable or a temp table.
You can use CTE to define a base query which can be used multiple times in the same scope of the code:
WITH Sales_CTE (returnParam1, returnParam2, ...)
AS
-- Define the CTE query.
(
select ..... from ... complex and long query #2
)
Or you can create a user defined function which gets params and returns the result, then call it multiple times:
CREATE FUNCTION dbo.ufnGetInventoryStock(param1 int, ...)
RETURNS int
AS
RETURN (
select ..... from ... complex and long query #2
)

Transform SQL query with recursion into LINQ

I'm stuck on a task where I have to transform a Stored Procedure into a LINQ query.
The model:
AccountSet: Account table with columns 'AccountId', 'ParentAccountId' (references an 'AccountId') and 'Name'
ContactSet: Contact table with columns 'ParentCustomerId'
(references an Account via 'AccountId')
The Stored Procedure:
It should search for all accounts with the given id
Search all parents (recursive) for the accounts found in step 1
Fetch all contacts that have a ParentCustomerId matching an 'AccountId' found in step 2
CREATE PROCEDURE [dbo].[sp_GetContactsForCompany]
(
#projectid AS UNIQUEIDENTIFIER
)
AS WITH recursion ( AccountId, Name, ParentAccountId )
AS (
SELECT AccountId, Name, ParentAccountId
FROM dbo.AccountBase
WHERE AccountId = #projectid
UNION ALL
SELECT a.AccountId, a.Name, a.ParentAccountId
FROM dbo.AccountBase AS a
INNER JOIN recursion AS b ON a.ParentAccountId = b.AccountId
)
SELECT ContactId, FullName
FROM dbo.ContactBase
WHERE ParentCustomerId IN (
SELECT AccountId
FROM recursion
)
ORDER BY FullName
LINQ:
from a in allAccs
where a.AccountId == id
select a;
This gives me all the accounts with the given id. But now I have no idea how to apply the join and recursion.
Any hint would be great.

get same result from c# linq as SQL statement

I am trying to figure out how to get all the notifications from relations that get multiple notifications, because i want to combine these notifications to 1 notification so the relation wil only get 1 e-mail instead of multiple.
I created the following SQL statement, which for as far as i can tell does what i want:
select distinct r.Notificatie
, r.RelatieNr
FROM [configuratie].[dbo].[NotificatieRecID] r
join [configuratie].[dbo].[Notificatie] n on r.Notificatie = n.ID
where n.Verzonden = 0
and r.RelatieNr in(select RelatieNr from [configuratie].[dbo].[NotificatieRecID]
group by RelatieNr having count(*) > 1)
order by r.RelatieNr
It returns the following
Notification Relation
3A2A53B9-D92A-4504-874D-5A901AD01041 114147
4C499F6C-53C8-49E0-B529-8B045819BE10 114147
AF4ED8CB-D033-47A4-96AE-F379BB484532 114147
977885C5-4C12-431B-AB72-59383B1824C6 303327
3A2A53B9-D92A-4504-874D-5A901AD01041 303327
4C499F6C-53C8-49E0-B529-8B045819BE10 303327
AF4ED8CB-D033-47A4-96AE-F379BB484532 303327
Later in my c# code i will get all the values from the different notifications and simply combine them but first i need to write this SQL statement in a way i can use it with linq in c#.
I have no idea how to do SELECT DISTINCT, and r.RelatieNr in and group by RelatieNr having count(*) > 1
Could someone provide me with an example? (it does not have to be 1 linq statement, i've kind of figured that's impossible, though i would like as little temporary Lists/Iqueriables since the tables are huge)
You can use the following
var details= (from r in NotificatieRecID
join n in Notificatie on r.Notificatie=n.ID
where n.Verzonden=0 &&
(from t in NotificatieRecID
group t by t.RelatieNr into grp
where grp.Count()>1
select grp.Key).Contains(r.relatieNr)
select new {
Notificate=r.Notificatie,
RelatieNr=r.RelatieNr
}).Distinct();

NHibernate: hql to criteria query - help needed

I have this hql query, which works perfect:
select m
from Media m
join m.Productlines p
join m.Categories c
join m.Spaces sp
join m.Solutions so
where m.Uid != 0
and p.Uid in (:productlines)
and c.Uid in (13)
and sp.Uid in (52)
and so.Uid in (15,18)
group by m.Uid
But now it needs to be parameterized/made dynamic, not only the parameters, but also the joins (it is possible to select only from Media, without any joins, and so no *.Uid in will be required in this case).
I dont want to mess around with a StringBuilder instance and build the hql query that way, I would rather like to use the Criteria API, but I cant get a
SELECT m.*
....
GROUP BY m.Uid
query to work with Criteria.
If I add a
Projections.GroupProperty("Uid")
to my query, nhibernate selects
SELECT m.Uid
....
GROUP BY m.Uid
which is of course wrong.
After that, I also need to count the unique rows the query returned, as the result is paged.
So, my other query is quite similiar, but I cant find a Criteria equivalent for
SELECT COUNT(DISTINCT m.Uid)
Here is the HQL:
select count(distinct m.Uid)
from Media m
join m.Productlines p
join m.Categories c
join m.Spaces sp
join m.Solutions so
where m.Uid != 0
and p.Uid in (:productlines)
and c.Uid in (13)
and sp.Uid in (52)
and so.Uid in (15,18)
How can this be done with Criteria API?
Please, (N)Hibernate experts - help me with this, I cant find a working solution. Any help is greatly appreciated!
Group columns are implicitly returned as result, but you can add more columns. AFAIK, you can return full entities:
var query = session.CreateCriteria(typeof(Media), "m")
.Add(Projections.GroupProperty("m"))
.Add(Restrictions.NotEq("m.Uid", 0));
// dynamically add filters
if (filterProductLines)
{
query
.CreateCriteria("m.Productlines", "p")
.Add(Restrictions.Eq("p.Uid", productLines));
}
// more dynamic filters of this kind follow here...
IList<Media> results = query.List<Media>();
To count the full number of results you can just build up the same query with different projection:
var query = session.CreateCriteria(typeof(Media), "m")
.SetProjection(Projections.CountDistinct("m.Uid"));
// rest of the query the same way as above
long totalNumberOfResults = query.UniqueResult<long>();
I'm getting unsure about the Projections.GroupProperty("m"), you need to try this. If it doesn't work, you could make it an DetachedQuery that only returns ids:
var subquery = DetachedCriteria.For(typeof(Media), "m")
.Add(Projections.GroupProperty("m.Uid"))
.Add(Restrictions.NotEq("m.Uid", 0));
// add filtering
var query = session.CreateCriteria(typeof(Media), "outer")
.Add(Subqueries.PropertyIn("outer.Uid", subquery));
IList<Media> results = query.List<Media>();
This creates a sql query like this:
select outer.* // all properties of Media to create an instance
from Media outer
where outer.Uid in (
select Uid
from media m
where // filter
)
var count = session.CreateCriteria(typeof(Media))
// Add other criterias...
.SetProjection(Projections.CountDistinct("Id")) // or whatever the id property of Media class is called
.UniqueResult<long>();
As to your GROUP BY question, the query:
SELECT m.*
....
GROUP BY m.Uid
makes no sense because you need to select only columns that appear in the group by clause or aggregate functions. Could you elaborate a little more as to what exactly are you trying to achieve?

Categories

Resources