Member 14800672 Ответов: 1

Как получить несуществующие записи


Я сижу за этим столом целый день
DayId   Name
---   ----
1      sun
2      mon
3      tue
4      wed



А это место за столом
PlaceId  Loc  DayId
1      1     1
1      1     2
1      2     1
2      1     3
3      1     2
3      1     4



я хочу вернуть дни, которые не используются для каждого (PlaceId и LocId), поэтому результат должен быть следующим

PlaceId  Loc  DayId
1      1     3
1      1     4
1      2     2
1      2     3
1      2     4
2      1     1
2      1     2
2      1     4
3      1     1
3      1     3


Что я уже пробовал:

Я пробовал это сделать но ничего не вышло
select distinct Place.PlaceId,Place.Loc, Place.DayId from place
left join (
select DayId from Day where DayId not in(
select distinct dayId from Place) 
) q on q.DayId<>Place.DayId 

Daniele Rota Nodari

Результат (третья таблица) не является представлением того, что вы просите.
Все дни из первой таблицы используются во второй таблице (присутствуют все значения DayId).
Может быть, вам следует уточнить, что вы имеете в виду под "используется" или "не используется".
Означает ли "используется", что комбинация PlaceId+Loc имеет этот конкретный DayId?

Member 14800672

да, я имею в виду то, что не используется для PlaceId и Loc вместе взятых. (я обновил вопрос). Не могли бы вы помочь?

1 Ответов

Рейтинг:
7

Daniele Rota Nodari

select distinct Place.PlaceId, Place.Loc, Day.DayId
from Place
cross join Day
left join Place AS X
on Place.PlaceId = X.PlaceId
and Place.Loc = X.Loc
and Day.DayId = X.DayId
where x.DayId is null


Этот запрос сначала производит перекрестное соединение между местом и днем (с места Креста присоединяйтесь ко Дню), чтобы генерировать все возможные комбинации.
Затем попробуйте соединить каждую (произведенную) запись с соответствующей записью внутри места (левое место соединения).
Затем исключается вся запись, в которой совпадение не найдено (где X.DayId имеет значение null).

Если хотите, вы можете обернуть перекрестное соединение в подзапрос, чтобы отделить его логику от левого соединения
select _All.* from
(
select distinct Place.PlaceId, Place.Loc, Day.DayId
from Place, Day
) as _All
left join Place AS X
on _All.PlaceId = X.PlaceId
and _All.Loc = X.Loc
and _All.DayId = X.DayId
where x.DayId is null


Member 14800672

Идеальный.. Спасибо :D

Member 14800672

Есть ли способ сделать это без четких и все еще не дублирующихся записей?

Daniele Rota Nodari

Записи дублируются, после чего необходимо дать команду обработчику запросов, чтобы избежать повторений.
Альтернативой DISTINCT является GROUP BY, но id не добавит ценности запросу; он сделает его более длинным и менее читабельным.
Единственный способ избежать дублирования-это предотвратить его, имея таблицу, содержащую только записи комбинации клавиш; то есть таблицу только с полями PlaceId и Loc, заполненную без повторений; это стало бы основной/родительской таблицей.

Member 14800672

У меня есть таблица, которая имеет как placeId, так и loc под названием placeLoc, где именно я должен добавить это в наш код?

Daniele Rota Nodari

Мой предыдущий ответ был потерян! :(
PlaceLoc заменяет место везде, где вы используете его для извлечения уникальных комбинаций.
Это означает, что внутри перекрестного соединения (и внутри _All). После подстановки ключевое слово DISTINCT больше не будет иметь значения, и вы можете удалить его.
Вы используете "выбрать особое место......" чтобы собрать именно то, что уже внутри PlaceLoc.