Как сделать полное внешнее объединение в Linq?

Я наследовал базу данных, которая не была разработана точно оптимально, и я должен управлять некоторыми данными. Позвольте мне дать более общую аналогию вида вещи, которую я должен сделать:

Скажем, у нас есть a Student таблица, a StudentClass учет ведущего таблицы всех классов он принял участие, и a StudentTeacher таблица, которая хранит всех учителей, которые учили этого студента. Да, я знаю, что это - немой дизайн, и имело бы больше смысла хранить учителя на таблице Class - но это - то, с чем мы работаем.

Я теперь хочу очистить данные, и я хочу найти все места, где у студента есть учитель, но никакие классы, или класс, но никакие учителя. SQL таким образом:

select *
from StudentClass sc
full outer join StudentTeacher st on st.StudentID = sc.StudentID
where st.id is null or sc.id is null

Как дела это в Linq?

36
задан Shaul says I Support Monica 18 January 2010 в 10:52
поделиться

3 ответа

- [1125422-

Я думаю, у меня есть ответ здесь, что не так элегантно, как я надеялся, но он должен сделать трюк:

var studentIDs = StudentClasses.Select(sc => sc.StudentID)
  .Union(StudentTeachers.Select(st => st.StudentID);
  //.Distinct(); -- Distinct not necessary after Union
var q =
  from id in studentIDs
  join sc in StudentClasses on id equals sc.StudentID into jsc
  from sc in jsc.DefaultIfEmpty()
  join st in StudentTeachers on id equals st.StudentID into jst
  from st in jst.DefaultIfEmpty()
  where st == null ^ sc == null
  select new { sc, st };

Вы, вероятно, могли выжать эти два утверждения в одну, но Я думаю, что вы пожертвоваете ясность кода.

28
ответ дан 27 November 2019 в 05:51
поделиться

Начало ...

 var q = from sc in StudentClass
            join st in StudentTeachers on sc.StudentID equals st.StudentID into g
            from st in g.DefaultIfEmpty()
            select new {StudentID = sc.StudentID, StudentIDParent = st == null ? "(no StudentTeacher)" : st.StudentID...........};

См. Также http://www.linqpad.net/ для получения дополнительных образцов Хороший инструмент для игры с

1
ответ дан 27 November 2019 в 05:51
поделиться

Я предлагаю вам преобразовать ваши данные в новую структуру данных, такую, как это:

name_data {  
  string name;
  int[] amounts;
}

Вы бы связываете ваш повторитель в список (name_data>.

, чтобы создать это, во-первых, итерации через и данные списки списки и сохраняют список (список, вероятно) всех уникальных лет, которые вам нужно сообщать о. Сортировать результирующий список, так что годы в порядке. Теперь индексы списка лет Соответствуйте номерам столбцов в вашей выходной таблице. Далее, повторяется переписывание элемента , на этот раз создание нового объекта name_data для каждого элемента объект. Имя_data конструктор будет выглядеть так :

public name_data(string name, int yearCount) {
  this.name = name;
  amounts = new int[yearCount];
}

Годка - это количество предметов в списке «Год».

Наконец, шаг через список данных для текущего элемента , посмотрите в год в год Список, чтобы получить индекс, затем наклейте значение суммы в поле суммы в соответствующем слоте . Добавьте ваше заполненное name_data в список.

на CE Вы сделали, вы должны быть в состоянии связать список имени_дата к вашему ретрему

-121--4378960-

Для данных 2 коллекций A и B , требуемое полное наружное соединение может быть следующим:

a.Union(b).Except(a.Intersect(b));

Если A и B не Из того же типа, то 2 отдельные нелевые внешние соединения требуются:

var studentsWithoutTeachers =
    from sc in studentClasses
    join st in studentTeachers on sc.StudentId equals st.StudentId into g
    from st in g.DefaultIfEmpty()
    where st == null
    select sc;
var teachersWithoutStudents =
    from st in studentTeachers
    join sc in studentClasses on st.StudentId equals sc.StudentId into g
    from sc in g.DefaultIfEmpty()
    where sc == null
    select st;

Вот один вариант, используя Concat ():

(from l in left
 join r in right on l.Id equals r.Id into g
 from r in g.DefaultIfEmpty()
 where r == null
 select new {l, r})
     .Concat(
     from r in right
     join sc in left on r.Id equals sc.Id into g
     from l in g.DefaultIfEmpty()
     where l == null
     select new {l, r});
18
ответ дан 27 November 2019 в 05:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: