Адресная книга: превратить запрос «хотя бы одного списка достаточно» в «все списки должны присутствовать» - PullRequest
0 голосов
/ 24 апреля 2019

У меня есть база данных SQLite3, которая содержит, среди прочего, следующие пять таблиц: Схема адресной книги SQL

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

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

SELECT DISTINCT `contact`.* FROM `contact` JOIN (
  SELECT `contact_id` FROM `contact_list` JOIN (
    SELECT `list_id` FROM `job_list` WHERE `job_id` = :id
  ) AS `inner` ON `inner`.`list_id` = `contact_list`.`list_id`
) AS `outer` ON `outer`.`contact_id` = `contact`.`id`

Я рассматриваю это как «хотя бы один список достаточно хорош», но мне нужно «все списки должны быть назначены и для работы».

Как выглядит такой запрос?

Edit:

Вот некоторые запросы, которые генерируют пример данных: Пример данных SQL

А вот ожидаемые результаты для каждого задания на печать:

job_id      contact_id
1           1, 2, 3
2           5
3           4, 6

Контакт 7 никогда не должен появляться

Результат

SELECT * FROM contact WHERE id IN (
  WITH flattenJob (job_id, jlist) AS (
    SELECT job_id, group_concat(list_id) 
    FROM job_list
    GROUP BY job_id
  ),
  flattenCont (contact_id, clist) AS (
    SELECT contact_id, group_concat(list_id)
    FROM contact_list
    GROUP BY contact_id
  )
  SELECT contact_id
  FROM flattenJob
  JOIN flattenCont ON jlist = clist
  WHERE job_id = :id
)
ORDER BY name

1 Ответ

0 голосов
/ 25 апреля 2019

Похоже, что цель состоит в том, чтобы напечатать один конверт на контакт (сэкономить деньги, сохранить окружающую среду, Yay!);по существу, дедупликация списков.Идея состоит в том, чтобы превратить «сложную работу» (например, работу 3) в свою собственную сущность.Одним из способов было бы использование виртуальных таблиц, что-то вроде этого:

WITH flattenJob (job_id,jlist) as
 (select job_id,group_concat(list_id) 
 from job_list
 group by job_id
 ),
 flattenCont (contact_id,clist)
 as (select contact_id,group_concat(list_id)
 from contact_list
 group by contact_id
 )
 select job_id,contact_id,jlist,clist
 from flattenJob
 JOIN flattenCont on jlist = clist

Это результат выборки данных:

job_id      contact_id  jlist       clist
----------  ----------  ----------  ----------
1           1           1           1
1           2           1           1
1           3           1           1
2           5           2           2
3           4           1,2         1,2
3           6           1,2         1,2

Это должно дать вам хорошую отправную точку для созданияуспешный запрос.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...