有趣的多对多sql连接

发布于 2024-07-08 07:54:46 字数 1214 浏览 8 评论 0原文

我有三个相关表“A(id, val)”、“B(id, val)”和一个值为“AB(aid, bid, val)”的链接表,

我正在查询 B 以带回 A 值,例如:

SELECT A.* 
FROM A INNER JOIN AB ON A.id = AB.aid INNER JOIN B ON AB.bid = B.id
WHERE B.val = 'foo';

每个 A 都有许多 B,每个 B 都有许多 A。

我遇到的问题是需要过滤集合,以便查询仅当 AB.val 是任何给定 A/B 对的最大值时才返回行

。 如果我有数据:

A

id   val
1    something
2    somethingelse

B

id   val
1    foo
2    bar

AB

aid  bid  val
1    1    3
1    2    2
2    1    1
2    2    4

我只想选择 AB 的第一行和最后一行,因为它们是每个 A 的最大值,然后能够查询 B.val = 'foo' 以仅返回第一行。 我不知道如何限制 AB 表中的 max val 行。

我能得到的最好的结果是

SELECT * 
FROM A 
INNER JOIN 
  (SELECT aid, bid, MAX(val) AS val FROM AB GROUP BY aid) as AB
  ON A.id = AB.aid 
INNER JOIN B ON AB.id = B.id
WHERE B.val = 'foo'

但这不太有效。 首先,这感觉是错误的方法,其次,它返回了错误的出价。 也就是说,子查询返回的 bid 不一定与 max(val) 来自同一行。 我相信这是一个已知的分组问题,其中未定义未定义未指定列的排序规则或分组时要返回的值的选择。

我希望上面的一些内容是有道理的,在过去的几个小时里,我一直在用头撞墙,任何帮助都将非常感激。 谢谢。

(对于那些想知道的人来说,它的实际用途是用于字典后端,其中 A 是单词表,B 是音素表。AB 是带有“位置”列的 WordPhoneme 表。查询是查找以结尾的所有单词指定的音素(音素是一个单词的发音,用法类似于国际音标)

I have three related tables "A(id, val)", "B(id, val)", and a link table with a value "AB(aid, bid, val)"

I am querying against B to bring back A values, for example:

SELECT A.* 
FROM A INNER JOIN AB ON A.id = AB.aid INNER JOIN B ON AB.bid = B.id
WHERE B.val = 'foo';

Every A has many B's and every B has many A's.

And the catch that I'm falling apart on is the need to filter the set so that the query returns rows only when AB.val is a max for any given A/B pair

E.g. if I have the data:

A

id   val
1    something
2    somethingelse

B

id   val
1    foo
2    bar

AB

aid  bid  val
1    1    3
1    2    2
2    1    1
2    2    4

I would want to select only the first and last rows of AB since they are the max values for each of the A's and then be able to query against B.val = 'foo' to return only the first row. I don't have a clue on how I can constrain against only the max val row in the AB table.

The best I've been able to get is

SELECT * 
FROM A 
INNER JOIN 
  (SELECT aid, bid, MAX(val) AS val FROM AB GROUP BY aid) as AB
  ON A.id = AB.aid 
INNER JOIN B ON AB.id = B.id
WHERE B.val = 'foo'

but this doesn't quite work. First, it just feels to be the wrong approach, second, it returns bad bid values. That is, the bid returned from the subquery is not necessarily from the same row as the max(val). I believe this is a known group by issue where selection of values to return when the column is not specified for either collation or grouping is undefined.

I hope that some of the above makes sense, I've been banging my head against a wall for the past few hours over this and any help at all would be hugely appreciated. Thanks.

(For those wondering, the actual use of this is for a Dictionary backend where A is the Word Table and B is the Phoneme Table. AB is the WordPhoneme table with a 'position' column. The query is to find all words that end with a specified phoneme. (a phoneme is a word sound, similar in usage to the international phonetic alphabet )

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

被你宠の有点坏 2024-07-15 07:54:46

我认为您需要先进行另一次连接才能获取每个 a.id 的 ab 最大值。

像这样的事情:

select a.*
from a
left join (
    select aid, max(val) as val 
    from ab 
    group by aid
) abmax on abmax.aid=a.id
inner join ab on ab.aid=abmax.aid and ab.val=abmax.val
inner join b on b.id=ab.bid
where b.val='foo'

I think you need to do another join to get ab's max val for each a.id first.

Something like this:

select a.*
from a
left join (
    select aid, max(val) as val 
    from ab 
    group by aid
) abmax on abmax.aid=a.id
inner join ab on ab.aid=abmax.aid and ab.val=abmax.val
inner join b on b.id=ab.bid
where b.val='foo'
甜味拾荒者 2024-07-15 07:54:46

我经常使用以下技巧来获得每个组中最大的值:

SELECT a.*
FROM ab AS ab1
  LEFT OUTER JOIN ab AS ab2 ON (ab1.aid = ab2.aid AND ab1.val < ab2.val)
  JOIN a ON (ab1.aid = a.id)
  JOIN b ON (ab1.bid = b.id)
WHERE ab2.aid IS NULL
  AND b.val = 'foo';

该技巧是通过外连接将 AB 表连接到自身。 如果不存在具有相同 help 值和更大 val 值的行,则返回 ab1。 因此 ab1 具有给定辅助值的每组行的最大 val。

I often use the following trick to get the greatest per group:

SELECT a.*
FROM ab AS ab1
  LEFT OUTER JOIN ab AS ab2 ON (ab1.aid = ab2.aid AND ab1.val < ab2.val)
  JOIN a ON (ab1.aid = a.id)
  JOIN b ON (ab1.bid = b.id)
WHERE ab2.aid IS NULL
  AND b.val = 'foo';

The trick is to join to the AB table to itself in an outer join. Return ab1 where no rows exist with the same value for aid and a greater value for val. Therefore ab1 has the greatest val per group of rows with a given value for aid.

习惯成性 2024-07-15 07:54:46

这是我刚刚测试过的另一种方法:

select a.*
from ab
   inner join b on(ab.bid=b.id)
   inner join a on (ab.aid=a.id)
where ab.val = (select max(val) from ab AS ab2 where ab2.aid = ab.aid)
   and b.val='foo'

Here's another way that I just tested out:

select a.*
from ab
   inner join b on(ab.bid=b.id)
   inner join a on (ab.aid=a.id)
where ab.val = (select max(val) from ab AS ab2 where ab2.aid = ab.aid)
   and b.val='foo'
锦上情书 2024-07-15 07:54:46

我不确定您使用的是哪个sql,但在MS SQL中,我创建了一个表值数据库函数来返回表A中的最大值,然后将其连接到表B。当我回头看时,我发现这比复杂的连接更容易理解关于我稍后的询问。

I am not sure which sql you are using but in MS SQL I create a table-valued database function to return the max values from table A then join this to table B. I find this much easier to understand than complex joins when I look back on my queries at a later stage.

鸠魁 2024-07-15 07:54:46
SELECT *
FROM
(
  SELECT
    A.*,
    (SELECT top 1 AB.BID FROM AB WHERE A.AID = AB.AID ORDER BY AB.val desc) as BID
  FROM A
) as Aplus
JOIN B ON Aplus.BID = B.BID
SELECT *
FROM
(
  SELECT
    A.*,
    (SELECT top 1 AB.BID FROM AB WHERE A.AID = AB.AID ORDER BY AB.val desc) as BID
  FROM A
) as Aplus
JOIN B ON Aplus.BID = B.BID
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文