Нужна помощь в ограничении объединения в Transact-sql - PullRequest
3 голосов
/ 15 апреля 2010

Я немного новичок в SQL и мне нужна помощь с синтаксисом запроса.

Моя проблема связана с двумя таблицами в более крупном объединении нескольких таблиц в Transact-SQL (анализатор запросов MS SQL Server 2000)

У меня есть АККАУНТЫ и ЛОГИНЫ, которые объединены в 2 поля: Сайт и Подмножество. Обе таблицы могут иметь несколько строк для каждой комбинации сайта / подмножества.

ACCOUNTS:                                 | LOGINS:
  SITE    SUBSET  FIELD   FIELD   FIELD   |   SITE    SUBSET  USERID  PASSWD
  alpha   bravo   blah    blah    blah    |   alpha   bravo   foo     bar
  alpha   charlie blah    blah    blah    |   alpha   bravo   bar     foo
  alpha   charlie bleh    bleh    blue    |   alpha   charlie id      ego
  delta   bravo   blah    blah    blah    |   delta   bravo   john    welcome
  delta   foxtrot blah    blah    blah    |   delta   bravo   jane    welcome
                                          |   delta   bravo   ken     welcome
                                          |   delta   bravo   barbara welcome

Я хочу выбрать все строки в СЧЕТАХ, которые имеют записи для входа в систему, , но только 1 логин для учетной записи.

DESIRED RESULT:
  SITE    SUBSET  FIELD   FIELD   FIELD   USERID  PASSWD
  alpha   bravo   blah    blah    blah    foo     bar
  alpha   charlie blah    blah    blah    id      ego
  alpha   charlie bleh    bleh    blue    id      ego
  delta   bravo   blah    blah    blah    jane    welcome

Меня не волнует какая строка из таблицы входа в систему, которую я получаю, но ID пользователя и пароль должны соответствовать. [Не возвращайте недопустимые комбинации, такие как foo / foo или bar / bar]. В MS Access есть удобная функция FIRST, которая может это сделать, но я не нашел эквивалента в TSQL.

Кроме того, если это имеет значение, другие таблицы объединяются со СЧЕТАМИ, но это единственное использование ЛОГИНОВ в структуре.

Спасибо очень большое за любую помощь.

Быстро добавленная информация: комбинации USERID / PASSWD уникальны для всей таблицы LOGIN.

Ответы [ 4 ]

1 голос
/ 18 апреля 2010

Я попробовал несколько из этих ответов с ограниченной степенью успеха.

Я в конце концов решил проблему, соединив поля USERID и PASSWD в операторе select и использовал значение MAX, чтобы вернуть только одно.

Другими словами:

SELECT ac.SITE, ac.SUBSET, MAX('user='lo.USERID+'&password='+lo.PASSWD) as IdPwd
FROM ACCOUNTS ac, LOGIN lo
WHERE ac.SITE = lo.SITE
AND ac.SUBSET = lo.SUBSET
GROUP BY ac.SITE, ac.SUBSET
1 голос
/ 15 апреля 2010

Было бы проще с полем автонумерации. У вас нет хорошего первичного ключа для этой таблицы.

Select *
From
(
   Select max(id) as MaxID, Site, Subset
   from logins 
   group by site, subset
) UniqueLogins
INNER JOIN logins on UniqueLogins.MaxID = Logins.ID
INNER JOIN Accounts ON logins.site = accounts.site and logins.subset = accounts.subset

Edit: Если вы не можете изменить схему, вы всегда можете выгрузить записи во временную таблицу с автономным номером, но это может быть неэффективно, если это часто выполняется, но это будет работать.

Редактировать снова: Если вы выбрали подход с временными таблицами, код для этого:

create table #tmp(
    ID int identity(1,1) primary key
    ,Site <data type>
    ,Subset <data type>
    ,userid <data type>
    ,password <data type>
)

Insert into #tmp(Site 
    ,Subset 
    ,userid 
    ,password )
Select * From logins
--where ???

Select *
From
)
    Select #tmp.* From(
       Select max(id) as MaxID, Site, Subset
       from #tmp 
       group by site, subset
    ) UniqueSites
    INNER JOIN #tmp on #tmp.ID = UniqueSites.MaxID
) UniqueLogins
INNER JOIN Accounts ON UniqueLogins.Site = Accounts.Site and UniqueLogins.Subset = Accounts.Subset

--do whatever else
drop table #tmp
0 голосов
/ 15 апреля 2010

Это может работать, если предположить, что комбинации USERID / PASSWD уникальны для комбинации SITE / SUBSET

select a.*, l1.USERID, l1.PASSWD
from ACCOUNTS a
    join LOGINS l1 on a.SITE = l1.SITE and a.SUBSET = l1.SUBSET
where not exists (select * from LOGINS l2 where l1.SITE = l2.SITE and l1.SUBSET = l2.SUBSET and l2.USERID < l1.USERID and l2.PASSWD < l1.PASSWD);

также попробуйте это, чтобы увидеть, работает ли он быстрее

select a.*, l1.USERID, l1.PASSWD
from ACCOUNTS a
    join LOGINS l1 on a.SITE = l1.SITE and a.SUBSET = l1.SUBSET
    left outer join LOGINS l2 on l1.SITE = l2.SITE and l1.SUBSET = l2.SUBSET and l2.USERID < l1.USERID and l2.PASSWD < l1.PASSWD
where l2.SITE is null;

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

0 голосов
/ 15 апреля 2010

Вот запрос, который может работать

Select accounts.Site, accounts.Subset, Logins.UserId, Logins.Passwd
From Accounts 
Inner Join
(
    select top 1 Site, Subset, UserId, Passwd
    From Logins logn
    Where Exists
    (
        Select 1
        From Accounts Acc
        where 1=1
        and Acc.Site = Logn.Site
        and Acc.Subset = Logn.Subset
    )
) as OneLoginPerSite
On  Accounts.Site = OneLoginPerSite.Site
and Accounts.Subset = OneLoginPerSite.Subset

Inner SELECT получает только один логин для каждой учетной записи, а затем вы присоединяете его обратно к учетным записям, чтобы получить окончательный результат.

...