基本的多对多sql选择查询

时间:2009-01-23 16:44:32

标签: sql ms-access many-to-many

我认为这应该很容易,但它正在躲避我。我在帐户和帐户组之间建立了多对多的关系。帐户可以在零个或多个组中,因此我使用的是标准连接表。

Accounts 
--------
ID
BankName
AcctNumber
Balance

AccountGroups
-------------
ID
GroupName

JoinAccountsGroups
------------------
AID
GID

我正在使用MS Access,FWIW。此外,这是针对低带宽情况,因此代码优化不如简单/可读性那么重要。

我正在使用php作为表示层,因此来自Access的简单结果很好。

至于如何处理多结果情况,我实际上有两件事我正在努力建立。第一个列出了一列中的所有组:

Bank       AcctNum       Balance    Groups
--------|--------------|----------|----------------
Citi       930938        400        Payroll
HSBC       8372933       100        Monthly, Payroll
Wells      09837         800        -
Chase      8730923       250        Monthly

第二个是主要细节列表:

Name          AcctNum    Balance
------------|----------|----------
Payroll (2)              500
  Citi        930938     400
  HSBC        8372933    100         
..................................
Monthly (2)              350
  HSBC        8372933    100         
  Chase       8730923    250
..................................
Wells         09837      800

对于master-detail,我的计划只是从db获取一个大的结果集,并根据需要在php中进行munge。既然在php中会有一些重要的后期处理,也许我应该做三个单独的查询并在那里加入。 (因为我对这种语言比较熟悉。)

9 个答案:

答案 0 :(得分:1)

SELECT a.BankName, a.AcctNumber, a.Balance, ag.GroupName
FROM (Accounts a 
      LEFT JOIN JoinAccountsGroups jag 
      ON a.ID = jag.AID) 
      LEFT JOIN AccountGroups ag
      ON jag.GID = ag.GroupName;

将选择第一个表的数据,但是为了连接组(每月,工资单),您将需要一个用户定义函数(UDF),这对Jet不可用,因此需要在PHP中进行处理。

您可能希望阅读Understanding SQL Joins。它指的是MySQL,但大部分都适用于Jet。

答案 1 :(得分:1)

另一个想法......为什么不在Access中使用查询设计器。这应该花费大约30秒来设计“视图”。然后去看看它写的SQL。

答案 2 :(得分:0)

SELECT act.acctid AS AcctId, bankName, acctNumber, Balance, 
       NVL(jag.gid, '-') AS GroupID, NVL(gp.groupname, '-') AS GroupName
FROM accounts act 
     LEFT OUTER JOIN JointAccountGroups jag ON (act.id = jag.aid) 
     LEFT OUTER JOIN AccounGroups gp ON (jag.gid = gp.id)

NVL是一个函数,意思是“如果第一个参数为null,则返回第二个参数;否则,返回第一个参数”。 NVL恰好是Oracle的做法 - 所有数据库都有类似的东西,但它没有标准名称;查看Access如何做到这一点。

答案 3 :(得分:0)

SQL Server为此目的使用ISNULL()。我不确定这是否适用于Access。

答案 4 :(得分:0)

是的,我会将表示层用于NULL。

但我必须遗漏一些东西。我从你原来的尝试中得到了同样的错误:

Syntax error (missing operator) in query expression '(act.id = jag.aid) 
                  LEFT OUTER JOIN accountgroups gp ON (jag.gid = gp.id)'

答案 5 :(得分:0)

怎么样:

SELECT act.acctid AS AcctId, bankName, acctNumber, Balance, 
      jag.gid AS GroupID, gp.groupname AS GroupName
FROM accounts AS act 
     LEFT OUTER JOIN JointAccountGroups AS jag ON act.id = jag.aid
     LEFT OUTER JOIN AccounGroups AS gp ON jag.gid = gp.id

这会给你一个错误吗?一个更容易弄清楚的错误?

答案 6 :(得分:0)

我认为在Access中你可能想尝试类似的东西:

FROM (accounts AS act 
     LEFT OUTER JOIN JointAccountGroups AS jag ON act.id = jag.aid)
     LEFT OUTER JOIN AccounGroups AS gp ON jag.gid = gp.id

我不知道为什么括号很重要,但我尝试了一个测试,它似乎解决了它。

答案 7 :(得分:0)

另一个尝试:

SELECT act.acctid AS AcctId, bankName, acctNumber, Balance, 
    jag.gid AS GroupID, gp.groupname AS GroupName
FROM accounts AS act 
   LEFT OUTER JOIN JointAccountGroups AS jag ON act.id = jag.aid
   LEFT INNER JOIN AccounGroups AS gp ON jag.gid = gp.id

访问可能是两个OUTER JOINS有问题,所以我让第二个成为INNER JOIN应该可以工作

答案 8 :(得分:0)

不仅使用前面建议的查询设计器,还使用MS Access关系工具记录两个外键(AID,GID)和它们引用的主键之间的关系。

这使得在查询设计器中进行自然连接几乎是儿童游戏。您甚至可以在您概述的情况下使用查询向导。

一旦构建了查询,为什么不将查询用作记录源而不是使用表?

我在PHP中做的一件事就是将多个结果转换为以逗号分隔的列表。