Выберите идентификатор, в котором есть только одна строка, и эта строка является определенным значением

#sql #sql-server-2016

#sql #sql-server-2016

Вопрос:

У меня есть этот запрос. Существует множество соединений, потому что я проверяю, связан ли идентификатор с какой-либо из этих таблиц.

В настоящее время этот запрос показывает мне любые идентификаторы, которые не связаны ни с одной из этих таблиц. Я хотел бы добавить к нему, чтобы он также отображал любые идентификаторы, которые связаны с общей таблицей, но только если в общей таблице всего 1 строка, а тип в общем поле — ‘member’.

 SELECT 
    c.ID,
    c.location,
    c.pb,
    c.name,
    c.surname

FROM c
    LEFT JOIN l on c.rowno = l.rowno
    LEFT JOIN d on c.rowno = d.rowno
    LEFT JOIN t on c.rowno = t.rowno
    LEFT JOIN cj ON (c.rowno = cj.rowno OR c.rowno = cj.rowno2)
    LEFT JOIN dj ON c.rowno = d.rowno
    LEFT JOIN lg ON c.rowno = lg.rowno
    LEFT JOIN tj ON c.rowno = tj.rowno

WHERE
    c.status != 'closed'
    AND l.rowno IS NULL
    AND d.rowno IS NULL
    AND t.rowno IS NULL
    AND cj.rowno IS NULL
    AND dj.rowno IS NULL
    AND lg.rowno IS NULL
    AND tj.rowno IS NULL
  

Моя первая мысль — просто добавить

 WHERE D.type = 'member'
  

Но это дает мне все идентификаторы, в которых есть строка с D.type = member (у них может быть 10 строк с разными типами, но пока 1 из них имеет type = member, он отображается). Я хочу видеть идентификаторы, которые имеют только d.type = member

Извините, если я плохо формулирую, у меня возникли проблемы с тем, чтобы разобраться с этим в моей голове. Любая помощь приветствуется!

Комментарии:

1. Посмотрите, что произойдет, если вместо этого вы введете это условие в предложение ON.

2. вы заявляете / подразумеваете, что ваш запрос показывает таблицы со связанными строками на основе ID, но все ваши соединения основаны на другом поле (rowno), поэтому ваш запрос показывает связи на основе rowno. что такое rowno?

3. rowno — это PK, хотя идентификатор также является уникальным полем. для нашей базы данных rowno — это очень длинное число, поэтому у нас есть ID как более удобный для чтения идентификатор (я его не создавал)

Ответ №1:

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

 SELECT c.*
FROM c JOIN
     (SELECT d.rownum, COUNT(*) as cnt,
             SUM(CASE WHEN d.type = 'Member' THEN 1 ELSE 0 END)  as num_members
      FROM t
      GROUP BY d.rownum
     ) d
     ON c.rownum = d.rownum
WHERE c.status <> 'closed' AND          
      NOT EXISTS (SELECT 1 FROM t WHERE c.rowno = t.rowno) AND
      NOT EXISTS (SELECT 1 FROM l WHERE c.rowno = l.rowno) AND
      . . . 
  

Я считаю, NOT EXISTS что логически следовать проще. Я не думаю, что существует большая разница в производительности между двумя методами в SQL Server.

Комментарии:

1. производительность определенно становится проблемой с этим конкретным запросом — я обнаружил, что привязка ко многим таблицам немного замедляет работу. Я попробую этот способ, спасибо!