Простая проблема SQL - PullRequest
       2

Простая проблема SQL

2 голосов
/ 06 августа 2010

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

У меня есть таблица XXX:

Social Security No (SSN).
Name.
organisation. (Finance/IT)

На английском я хочу:

Чтобы выбрать все SSN и имена в «Финансы», если для этого SSN в «IT» есть другое имя.

Моя неработающая попытка:

выберите ssn, имя из XXX, где org = "Финансы", а имя не в (выберите имя из XXX, где org = "IT" и ssn = the_first_ssn)

Пожалуйста, помогите.


Я решил сделать это немного сложнее.

SSN может появляться несколько раз в «IT»:

Поэтому я хочу выбрать все SSN и Имена в Финансах, где SSN не существует с тем же Именем в «IT»

Ответы [ 4 ]

3 голосов
/ 06 августа 2010

Вы можете использовать подзапрос в предложении exists:

select  ssn, name
from    YourTable a
where   organisation = 'Finance'
        and exists
        (
        select  *
        from    YourTable b
        where   organisation = 'IT'
                and a.ssn = b.ssn
                and a.name <> b.name
        )

Подзапрос говорит, что в IT должна быть строка с тем же SSN, но с другим именем.

1 голос
/ 06 августа 2010

Предполагая, что ssn является уникальным ключом ...

select ssn, name 
from XXX XXX1
where org = "Finance" 
and ssn in 
(
select ssn 
from XXX XXX2
where org="IT"
and XXX1.name<>XXX2.name
)
0 голосов
/ 07 августа 2010

Я знаю, что опаздываю на вечеринку, но я работаю над изучением SQL, и я хотел попробовать свои силы в решении и сравнить с существующими ответами. Я создал таблицу Personnel с некоторыми данными тестирования.

  1. Мой запрос только к SQL Server использует CTE и INNER JOIN:

    WITH
        Finance AS (SELECT SSN, Name FROM Personnel WHERE Org = 'Finance'),
        IT AS (SELECT SSN, Name FROM Personnel WHERE Org = 'IT')
    SELECT Finance.SSN, Finance.Name
        FROM Finance
        INNER JOIN IT ON IT.SSN = Finance.SSN
        WHERE IT.Name != Finance.Name
    
  2. Решение Александра использует прямую INNER JOIN. Я переписал его немного, поместив сравнение имен в предложение WHERE и добавив DISTINCT, потому что это не требуется:

    SELECT Finance.SSN, Finance.Name
        FROM Personnel Finance
        INNER JOIN Personnel IT ON Finance.SSN = IT.SSN
        WHERE
            (Finance.Org = 'Finance' AND IT.Org = 'IT') AND
            (Finance.Name != IT.Name)
    
  3. Решение Andomar с использованием коррелированного подзапроса в предложении EXISTS:

    SELECT SSN, Name
        FROM Personnel a
        WHERE
            (Org = 'Finance') AND
            EXISTS
            (
                SELECT *
                    FROM Personnel b
                    WHERE (Org = 'IT') AND (a.SSN = b.SSN) AND (a.Name != b.Name)
            )
    
  4. решение Барриллойда с использованием коррелированного подзапроса в предложении IN:

    SELECT SSN, Name
        FROM Personnel p1
        WHERE
            (Org = 'Finance') AND
            SSN IN
            (
                SELECT SSN FROM Personnel p2
                    WHERE (Org = 'IT') AND (p1.Name != p2.Name)
            )
    

Я подключил все это к SQL Server, и оказалось, что запросы 1 и 2 генерируют один и тот же план запросов, а запросы 3 и 4 генерируют один и тот же план запросов. Разница между этими двумя группами заключается в том, что первая группа фактически выполняет INNER JOIN внутри, тогда как вторая группа вместо этого выполняет левое полусоединение. ( См. Здесь для объяснения различных типов соединений.)

Я предполагаю, что есть преимущество в производительности незначительное в пользу левого полусоединения; однако для бизнес-случая, если вы хотите увидеть какие-либо столбцы данных из правой таблицы (например, если вы хотите отобразить оба имен для их сравнения), вам придется полностью переписать эти запросы в используйте решение на основе INNER JOIN.

Итак, учитывая все это, я бы предпочел решение 2, потому что производительность очень похожа на 3 и 4, и она гораздо более гибкая, чем те. Мое решение делает оператор SELECT очень легко читаемым, но он более многословен, чем 2 и не так переносим. Я полагаю, что мой может быть лучше для удобочитаемости, если вам нужно выполнить дополнительную фильтрацию для каждой из двух «вложенных таблиц», или если результаты этого запроса будут использоваться в качестве промежуточного шага для дальнейшей цели.

0 голосов
/ 06 августа 2010
SELECT distinct
t1.ssn,
t1.name
from
xxx t1
inner join xxx t2 on t1.ssn=t2.ssn and t1.name<>t2.name
where t1.org='Finance' and t2.org='IT'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...