I need to query table for values in two duplicate columns - c#

I'm working in ASP.NET Core. I have a problem with querying rows which have same User_id and Definition_id, if there are any like that, I need ID of the row.
+----+---------+---------------+
| Id | User-id | Definition-id |
+----+---------+---------------+
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 2 | 2 |
| 4 | 3 | 1 |
| 5 | 4 | 1 |
| 6 | 4 | 1 |
| 7 | 5 | 2 |
| 8 | 6 | 1 |
+----+---------+---------------+
I need to query table like this, to return { 5, 6 } to me, because of them having same user AND definition ids.
I've tried Groupby for both values, but I can't get the IQueryable or IGrouping to give me the id of specific row.
I'd imagine it to work like that, but it ain't.
var placementsWithDuplicates =
from p in _context.Placements
group p by new { p.User_id, p.Definition_id } into what
select new
{
Id = what.Id,
User = what.User_id,
Defi = what.Definition_id,
};
foreach (var p in placementsWithDuplicates)
{
issues.Add(new IssueModel()
{
Type = "Praxe ID[" + p.Id + "]",
Name = "User id [" + p.User + "], Definition id [" + p.Defi + "]",
Detail = "So user shouldnt have data for more definitons!"
});
};
Thanks to Satish Hirpara for best answer, it needed a little update so I post the thing that ended up working well:
var B = from p in _context.Placements
group p by new { p.User_id, p.Definition_id } into what
where what.Count() > 1
select new
{
User_id = what.Key.User_id,
Definition_id = what.Key.Definition_id
};
var placementsWithDuplicates = from A in _context.Placements
join b in B on new { A.User_id, A.Definition_id } equals new { b.User_id, b.Definition_id }
select A;

Please find below SQL query:
SELECT A.*
FROM Placements A
INNER JOIN
(SELECT User_id, Definition_id FROM Placements
GROUP BY User_Id, Definition_id
HAVING COUNT(*) > 1) B
ON A.User_id = B.User_id AND A.Defination_id =
B.Defination_id
You can create a temp table to avoid join of sub query.
If you want linq query then I tried to create it from above query, please find it below:
--- sub query
var B = from p in Placements
group p by new { p.User_id, p.Definition_id } into what
where what.count() > 1
select new
{ User_id = what.User_id,
Definition_id =what.Definition_id
};
--- join
Var result = from A in Placements
Join B ON A.User_id = B.User_id
AND A.Defination_id = B.Defination_id
Select A
Please try this one.

Try This
var placementsWithDuplicates = from p in _context.Placements.Where(m => m.User_id == m.Definition_id)
select new {
Id = p.Id,
User = p.User_id,
Defi = p.Definition_id,
};
// this is same as the top one
var placementsWithDuplicates = from p in _context.Placements where p.User_id == p.Definition_id
select new {
Id = p.Id,
User = p.User_id,
Defi = p.Definition_id,
};
foreach (var p in placementsWithDuplicates)
{
issues.Add(new IssueModel()
{
Type = "Praxe ID[" + p.Id + "]",
Name = "User id [" + p.User + "], Definition id [" + p.Defi + "]",
Detail = "So user shouldnt have data for more definitons!"
});
};

Related

Join with max time in EF Core C#

SELECT *
FROM Jobs j
WHERE j.InsertTime = (SELECT MAX(InsertTime) FROM Jobs)
How convert this SQL script to C# query?
I try this but not worked:
from j in _dbContext.Jobs
group j by j.InsertTime into g
select g.OrderByDescending(s=>s.InsertTime).First() into item
select item;
Sample data:
title | insertTime
------|-------------
AA | 2022-05-03
B | 2022-05-03
A | 2022-05-04
B | 2022-05-04
Result:
title | insertTime
------|-------------
A | 2022-05-04
B | 2022-05-04
Use the following query:
var query =
from d in _dbContext.Jobs.Select(d => new { d.Title }).Distinct()
from j in _dbContext.Jobs
.Wehere(j => j.Ttle == d.Ttle)
.OrderByDescending(j => j.InsertTime)
.Take(1)
select j;

LINQ to SQL - Count number of certain item types in each order

For the sake of simplicity of this post, suppose I have data in an Orders table as follows. Here the CustomerId is a foreign key to Customers table. Question: How can we write a LINQ Query to find the count of vegetables (V) and the fruits (F) each customer ordered?
Orders Table:
OrderId | CustomerId | OrderType
1 | 11 | V
2 | 11 | V
3 | 11 | F
4 | 11 | V
5 | 12 | V
6 | 15 | F
7 | 15 | V
8 | 15 | F
I can count the number of orders for each customer as follows. But how about number of Vegetables and number of Fruits in each order?:
var Query1 = from o in Orders
group o by o.CustomerId
into grp
select new {CustomerId = grp.Key, OrderCount = grp.Count()};
You can to use a subquery:
var Query1 = from o in Orders
group o by o.CustomerId into grp
select new {
CustomerId = grp.Key,
OrderCount = grp.Count(),
OrderCounts = from g in grp
group g by g.OrderType into grp2
select new { OrderType = grp2.Key, Count = grp2.Count() }
};
or you can group by both CustomerId and OrderType:
var Query1 = from o in Orders
group o by new { o.CustomerId, o.OrderType } into grp
select new {
CustomerId = grp.Key.CustomerId,
OrderType = grp.Key.OrderType,
OrderCount = grp.Count()
};
They will both return the same data but in slightly different form.

Linq every occurrence of value, bind to ViewModel

I need to get a list of players and every team that said player is associated to and add it to my ViewModel.
ViewModel
public class PlayersViewModel
{
public long PlayerID { get; set; }
public string PlayerName { get; set; }
public List<long> TeamID { get; set; } //Players can be assigned to 1 or more teams
}
I have a few different datatables going on:
PlayersInTeams (linking table)
+------------+---------+
| PlayerID | TeamID |
+------------+---------+
| 1 | 10001 |
| 1 | 10002 |
| 2 | 10002 |
| 3 | 10001 |
+------------+---------+
Players
+------------+---------+-----------+
| PlayerID | ForeName| Surname |
+------------+---------+-----------+
| 1 | John | Doe |
| 2 | Pete | Noe |
| 3 | Evan | Soe |
+------------+---------+-----------+
So for the above example tables, Player 1 - John Doe should have an array of 2 teamIDs in the ViewModel [10001, 10002].
Aim
I'm trying to have a List<PlayersViewModel> with a collection of TeamIDs.
Code
public List<PlayersViewModel> GetPlayers()
{
var playersInTeam = new PlayersInTeamsBLL();
var pit = playersInTeam.GetPlayersInTeams();
var playerDetail = Players;
var list = from p in pit
join team in Teams on p.TeamID equals team.TeamID // Only get teams that related to club
join pd in playerDetail on p.PlayerID equals pd.PlayerID //Link a player to
where pd.IsArchived == false
select new PlayersViewModel { TeamID = team.TeamID, PlayerID = p.PlayerID, PlayerName = pd.Forename + " " + pd.Surname};
return list.ToList();
}
I'm getting null PlayerIDs and obviously my TeamID isn't getting populated.
Any suggestions / solutions?
Try something like this:
var viewModels = playerDetail.Select(p => new PlayersViewModel()
{
PlayerID = p.PlayerID,
PlayerName = String.Format("{0} {1}", p.ForeName, p.Surname),
TeamID = pid.Where(pidElement => pidElement.PlayerID == p.PlayerID)
.Select(pidElement => pidElement.TeamID).ToList()
}).ToList();
In general it seems to me you're trying to tackle the problem from the wrong end. You want a list of players first, and then their teams second, not a list of player-team associations first, and player details second, so you should start with the playerDetail object (I assume it's an IEnumerable of all Player objects).
On a side note: consider that you can add a getter to your Player class which would give you the full name without the need to always concatenate the name and surname. Something like:
public string FullName
{
get { return String.Format("{0} {1}", this.FirstName, this.Surname); }
}
var results = yourContext.Players
.Select(p => new PlayersViewModel
{
PlayerID = p.PlayerID,
PlayerName = p.PlayerName,
TeamID = context.PlayersInTeams.Where(x => x.PlayerID == p.PlayerID)
}).ToList();
You need group them using group by like this:
var teamsFinal = from p in pit
join pd in playerDetail on p.PlayerID equals pd.PlayerID
where pd.IsArchived == false
group new {p,pd} by new
{
pd.PlayerID ,
pd.ForeName,
pd.SurName
} into g
select new PlayersViewModel
{
TeamID = g.Select(x => x.p.TeamID).ToList(),
PlayerID = g.Key.PlayerID,
PlayerName = g.Key.ForeName + " " + g.Key.SurName
};
Check this working Fiddle example

How to find the min dates from the list of items?

I have a table structure like this
id | itemId | date |
1 | a1 | 6/14/2015
2 | a1 | 3/14/2015
3 | a1 | 2/14/2015
4 | b1 | 6/14/2015
5 | c1 | 6/14/2015
From this table structure I am trying to get all the distinct items that has min date. for e.g. I am trying to get id = 3,4 and 5.
I have tried following code but I couldn't
var items = (from i in _db.Items
//where min(i.date) // doesn't seem right
group i by i.itemID
into d select new
{
iId = d.Key,
}).Distinct();
Given your sample data, I would do this:
var query =
from i in _db.Items
group i by i.itemId into gis
let lookup = gis.ToLookup(x => x.date, x => x.id)
from x in lookup[gis.Min(y => y.date)]
select x;
var items = from i in _db.Items
group i.date by i.itemID
into d select new {
iId = d.Key, iDate = d.Min()
};

Sql Multiple Conditions Method

I've been trying to find a way of using multiple conditions with Sql, at the moment I am using Entity Framework. There is a very good chance that this is the only way to achieve what I want but I wondered if anyone knew a more efficient method.
Essentially I am using criteria to find the next row in the database which should be picked. For example lets use the 2 following conditions:
1) Field1 = A;
2) Field2 = B;
So in the following table:
| RowId | Field1 | Field2 |
| 0001 | A | B |
| 0002 | B | B |
| 0003 | C | C |
| 0004 | A | C |
I need to pick each row individually in the following order:
0001 - Both Condtions Satisfied,
0004 - Condition 1 Satisfied,
0002 - Condition 2 Satisfied,
0003 - No conditions satisfied
At the moment I am doing the following
public TestObj GetNextObj()
{
using (TestDb testDb = new TestDb())
{
TestObj testObj = (from o in testDb.TestTable
where o.Field1 == A && o.Field2 == B
select o).FirstOrDefault();
if (testObj != null)
return testObj;
testObj = (from o in testDb.TestTable
where o.Field1 == A
select o).FirstOrDefault();
if (testObj != null)
return testObj;
testObj = (from o in testDb.TestTable
where o.Field2 == B
select o).FirstOrDefault();
if (testObj != null)
return testObj;
testObj = (from o in testDb.TestTable
select o).FirstOrDefault();
return testObj;
}
}
This works okay, however I want to allow the conditions to be defined in a table and I am worried that when the number of conditions increases that this process will begin taking a very long time.
Is there another way to do what I am attempting here??
Thanks.
EDIT:::::
Now using the following code to select items from a table in order as defined by another table::
public static SortTest GetRow()
{
using (TestDb testDb = new TestDb())
{
SortParam[] sortParams = (from sp in testDb.SortParams
orderby sp.Priority ascending
select sp).ToArray();
if (sortParams.Length == 0)
{
SortTest sortTest = (from st in testDb.SortTests
orderby st.RowId ascending
select st).FirstOrDefault();
Console.WriteLine("Short route");
return sortTest;
}
Console.WriteLine("Long route");
StringBuilder sqlQueryBuilder = new StringBuilder();
sqlQueryBuilder.Append("SELECT * FROM [Proto].[dbo].[SortTests] ORDER BY \n");
foreach (SortParam sortParam in sortParams)
{
sqlQueryBuilder.Append("CASE WHEN " + sortParam.FieldName + " LIKE '%" + sortParam.FieldValue + "%' THEN 1 ELSE 2 END,\n");
}
sqlQueryBuilder.Append("\nRowId"); //By default use row Id
DbSqlQuery<SortTest> dbSqlQuery = testDb.SortTests.SqlQuery(sqlQueryBuilder.ToString());
return dbSqlQuery.FirstOrDefault();
}
}
I may have to alter thigns to prevent Sql Injection, but this works for now.
THANKS!
There's a simple way of doing it in a single query in SQL:
select *
from o
order by case Field1 when 'A' then 1 else 2 end,
case Field2 when 'B' then 1 else 2 end,
RowId

Categories

Resources