代码之家  ›  专栏  ›  技术社区  ›  MsLis

需要帮助限制Transact-SQL中的联接

  •  3
  • MsLis  · 技术社区  · 15 年前

    我对SQL有些陌生,需要有关查询语法的帮助。

    我的问题涉及Transact-SQL(MS SQL Server 2000查询分析器)下更大的多表联接中的两个表。

    我有帐户和登录名,这些帐户和登录名在两个字段中联接:站点和子集。 对于每个站点/子集组合,两个表都可以有多行。

    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

    我要选择帐户中具有登录条目的所有行, 但只有 每个帐户登录。

    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 / bar / 酒吧 ]MS Access有一个方便的First函数,它可以做到这一点,但我在TSQL中没有找到等效的函数。

    另外,如果有区别的话,其他表将联接到帐户,但这是结构中唯一使用登录名的方法。

    谢谢你 非常 很感谢你的帮助。

    快速添加信息:用户ID/passwd组合在整个登录表中是唯一的。

    4 回复  |  直到 15 年前
        1
  •  1
  •   MsLis    15 年前

    我尝试了其中几个答案,但成功的程度有限。

    我最终通过连接select语句中的userid和passwd字段解决了这个问题,并使用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
        2
  •  1
  •   Jeremy    15 年前

    使用自动编号字段会更容易。您没有这个表的好主键。

    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
    

    编辑: 如果不能更改模式,则可以始终使用自动编号将记录转储到临时表中,但如果经常运行,则效率可能很低,但它会起作用。

    再次编辑: 如果您使用临时表方法,其代码是:

    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
    
        3
  •  0
  •   Raj More    15 年前

    这是一个可能有效的查询

    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
    

    内部选择只为每个帐户提供一个登录名,然后将其加入到帐户中以获得最终结果。

        4
  •  0
  •   Sean    15 年前

    假设每个站点/子集组合的userid/passwd组合是唯一的,这可能有效。

    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;
    

    (实际上没有尝试运行这些,因此可能有语法错误潜入某些地方)