Question

I Have 4 tables:

Position Table:

|     Position  |  PositionId  | 
|     driver    |     1        | 
|     clerk     |     2        |

position Skill table:

|  SkillId  |    skill     |     PositionId  |  
|     1     |   driving    |        1        |
|     2     |   drifting   |        1        |

Worker table:

|     Name     |    WorkerId | 
|     John     |     1       |
|     alex     |     2       |

Worker skill table:

|     skillId |    skill     |     WorkerId   |
|     1       |   driving    |        1       |
|     2       |   drifting   |        1       |

I join the position table with position Skill table and worker table with worker skill

What I'm having trouble with is how can I compare the two joined tables to have a result of

for example:

I need to know who's worker have all the specific skills that the position have

Like:

I Select position with positionId of 1 and have the skillname of driving and drifting I need to get the Worker with the same skills with driving and drifting also

so far i got this:

var PositionsWithSkills = (from a in db.Client_Customer_Position
                           where a.ID == position
                           select new
                           {
                               PositionID = a.ID,
                               RequiredSkills = (from b in db.Client_Customer_Position_Skills
                                                 where b.ClientCusPosId == a.ID
                                                 select b.SkillName)
                           }).ToList();

var WorkersWithSkills = (from x in db.Workers
                         select new
                         {
                             workerId = x.ID,
                             Skills = (from y in db.Worker_Skills
                                       where y.Worker_ID == x.ID
                                       select y.SkillName)
                         }).ToList();

var PositionWithSkilledWorkers = (from pos in PositionsWithSkills
                                  select new
                                  {
                                      PositionId = pos.PositionID,
                                      Workers = (from worker in WorkersWithSkills
                                                 where pos.RequiredSkills.All(skill => worker.Skills.Any(workerSkill => workerSkill == skill))
                                                 select worker.workerId)
                                  }).ToList();

the two query works well.. but the last query where i must compare the two query =.. i cant get the worker id and can i turn this to a stored proc?

Was it helpful?

Solution

Sorry if am wrong. What I got to know from your question is you want the workers list satisfying all the skills of the position you pass. If this is what you want you may try this:

 var workerWithallSkill = (from u in db.workerList join x in db.workerSkillList on    u.WorkerId equals x.WorkerId 
 where ((from y in db.workerSkillList where y.WorkerId == u.WorkerId select y).Count() == (from p in db.positionSkillList where p.PositionId == 1("pass your positionId here") select p).Count()) 
select u).ToList().Distinct();

or if you want to use lambda expression you can use this

var workerWithallSkill = (from u in workerList join x in workerSkillList on u.WorkerId equals x.WorkerId where (workerSkillList.Where(y=> y.WorkerId == u.WorkerId).Count() ==  positionSkillList.Where(p=>p.PositionId == 1).Count()) select u).ToList().Distinct();

For more understanding you can try the below code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication8
{
    class Program
    {
        static void Main(string[] args)
        {

            IList<Position> positionList = new List<Position>() { 
                new Position(){ position="Driver", PositionId=1}
                ,new Position(){ position="clerk", PositionId=2}
              };


            IList<PositionSkill> positionSkillList = new List<PositionSkill>() {
                new PositionSkill(){ Skill = "driving",skillid = 1,PositionId = 1}
               ,new PositionSkill(){ Skill = "drifting",skillid = 2,PositionId = 1}
            };

            IList<Worker> workerList = new List<Worker>() {
             new Worker(){ name = "John",WorkerId = 1}
            ,new Worker(){ name = "alex",WorkerId = 2}
            };

            IList<WorkerSkill> workerSkillList = new List<WorkerSkill>(){
                new WorkerSkill(){Skill = "driving",skillid = 1,WorkerId = 2}
                , new WorkerSkill(){Skill = "drifting",skillid = 2,WorkerId = 2}
            };

            var workerWithallSkill = (from u in workerList join x in workerSkillList on u.WorkerId equals x.WorkerId where (workerSkillList.Where(y => y.WorkerId == u.WorkerId).Count() == positionSkillList.Where(p => p.PositionId == 1).Count()) select u).ToList().Distinct();

            foreach (var worker in workerWithallSkill)
            {
                Console.WriteLine(worker.name);
            }

            Console.ReadLine();

        }
    }


    public class Position
    {
        public string position { get; set; }
        public int PositionId { get; set; }
    }

    public class PositionSkill
    {
        public int skillid { get; set; }
        public string Skill { get; set; }
        public int PositionId { get; set; }
    }

    public class Worker
    {
        public string name { get; set; }
        public int WorkerId { get; set; }
    }

    public class WorkerSkill
    {
        public int skillid { get; set; }
        public string Skill { get; set; }
        public int WorkerId { get; set; }
    }

}

if a worker has skills from different positions the above code will not work, if this is the scenario try the below code:

var WorkerPositionSkill = from p in db.positionSkillList join q in db.workerSkillList on p.skillid equals q.skillid select new { posSkill = p, workerSkill = q };

 var workerWithallSkill = (from u in db.workerList join x in db.workerSkillList on u.WorkerId equals x.WorkerId where (WorkerPositionSkill.Where(y => y.workerSkill.WorkerId == u.WorkerId && y.posSkill.PositionId == 1).Count() == db.positionSkillList.Where(p => p.PositionId == 1).Count()) select u).ToList().Distinct();

OTHER TIPS

This is highly unlikely to work with Linq To SQL because...its a huge steaming pile of #$%&. But this Linq query should given a sufficiently magical IQueryProvider give the right SQL. I've seen some very magical things come from Entity Framework.

var PositionsWithSkills = from a in db.Client_Customer_Position
                          where a.ID == position
                          select new
                          {
                               PositionID = a.ID,
                               RequiredSkills = (from b in db.Client_Customer_Position_Skills
                                                 where b.ClientCusPosId == a.ID
                                                 select b.SkillName)
                          };

var WorkersWithSkills =  from x in db.Workers
                         select new
                         {
                             workerId = x.ID,
                             Skills = (from y in db.Worker_Skills
                                       where y.Worker_ID == x.ID
                                       select y.SkillName)
                         };

var PositionWithSkilledWorkers = from pos in PositionsWithSkills
                                 from worker in WorkersWithSkills
                                 where pos.RequiredSkill.All(worker.Skills.Contains)
                                 group worker.Name by pos.PositionID;

PS please learn to use associations as opposed to join/where. If you are going to use join/where, you might as well just use SQL.

  var PositionsWithSkills = (from a in Positions select new {
      PositionID = a.PositionId,
      RequiredSkills = (from b in PositionSkills where b.PositionId == a.PositionId select b.skillId).ToList()
  }).ToList();

  var WorkersWithSkills = (from x in Workers select new {
      Name = x.Name,
      Skills = (from y in WorkerSkills where y.WorkerId == x.WorkerID select y.skillId).ToList()
  }).ToList();

  var PositionWithSkilledWorkers = (from pos in PositionsWithSkills select new {
      PositionId = pos.PositionID,
      Workers = (from worker in WorkersWithSkills where pos.RequiredSkills.All(skill => worker.Skills.Any(workerSkill => workerSkill == skill)) select worker.Name).ToList()
  }).ToList();

i think, your database's tables have not been designed correctly... you need a relation between worker skill and position skill, i think your tables must be desinged like this:

Skill table: SkillID, Skill

Position table: PositionID, Position

PositionSkill table: ID, SkillID, PositionID

Worker table: WorkerID, Name

WorkerSkill table: ID, SkillID, WorkerID

but by this way you designed your tables, if assume skill field (description of skills) are the same in worker skill and position skill, we can use this as a relation, and your query can be like this:

// skills of specific position
var PositionSkills = Context.PositionSkill.Where(u => u.PositionId == 1);

var WorkersWithSkills = Context.Worker
    .Join(Context.WorkerSkill,
          worker => worker.WorkerId,
          workerSkill => workerSkill.WorkerId,
          (worker, workerSkill) => new { worker, workerSkill })
    .GroupBy(u => u.worker)
    .Select(u => new
    {
       u.Key.WorkerId,
       u.Key.Name,
       Skills = u.Select(t => t.workerSkill.skill)
    });

var SkilledWorkers = WorkersWithSkills
    .Where(u => PositionSkills.All(t => u.Skills.Contains(t.skill)))
    .ToList();

if you wont change your database's tables, you can add a join table between position skill and worker skill like:

WorkerPositionSkill: PositionSkillID, WorkerSkillID

Here is a LinqPad program that returns the result, { Worker = John, Position = Driver}. If I understand your requirements you want to find a worker who satisfies the conditions where the worker has all the skills required for Position = 1, which is driving and drifting skills. The query returns two rows the following [{worker = John, Position = Driver}, {worker = John, Position = Driver}]. I had to use distinct to display it once. The reason for two rows is he satisfies both driving and drifting job skills. If the position required 4 skills in which the worker met, there would be 4 duplicate rows. The unique fixes that problem. Hope this helps you along.

I created this solution in LinqPad, which is great tool with hundred's of very well documented linq query examples.

void Main()
{
    // Table Setup
    // ************
    var position = new List<Position>();
    position.Add(new Position { Id = 1, Name = "driver" });
    position.Add(new Position { Id = 2, Name = "clerk" });

    var positionSkill = new List<PositionSkill>();
    positionSkill.Add(new PositionSkill { Id = 1, Skill = "driving", PositionId = 1 });
    positionSkill.Add(new PositionSkill { Id = 2, Skill = "drifting", PositionId = 1 });

    var worker = new List<Worker>();
    worker.Add(new Worker { Id = 1, Name = "John" });
    worker.Add(new Worker { Id = 2, Name = "alex" });

    var workerSkill = new List<WorkerSkill>();
    workerSkill.Add(new WorkerSkill { Id = 1, Skill = "driving", WorkerId = 1 });
    workerSkill.Add(new WorkerSkill { Id = 2, Skill = "drifting", WorkerId = 1 });  

    // The Query
    // *********
    var positionValue = 1;

        var r = from p in position
                join ps in positionSkill on p.Id equals ps.PositionId
                join ws in workerSkill on ps.Skill equals ws.Skill
                join w in worker on ws.WorkerId equals w.Id
                where p.Id == positionValue
                select new {
                    PositionName = p.Name,
                    WorkerName = w.Name
                };

    // Get Distinct Names           
    r.Distinct().Dump();


}

// Define other methods and classes here
    public class Position
    {
        public int Id { get; set; }
        public string Name { get; set; }

    }


    public class PositionSkill
    {
        public int Id { get; set; }
        public string Skill { get; set; }
        public int PositionId { get; set; }

    }



    public class Worker
    {
        public int Id { get; set; }
        public string Name { get; set; }

    }


    public class WorkerSkill
    {
        public int Id { get; set; }
        public string Skill { get; set; }
        public int WorkerId { get; set; }

    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top