如何在保持唯一行的同时进行内部连接

时间:2018-05-24 08:43:18

标签: mysql sql join mariadb

我有三元关系,我坚持要约,简介和技能之间的关系。例如,名为ternary的三元关系表具有三个表的ID作为主键。它可能看起来像这样:

id_Offer    -   id_Profile  -   id_Skill
1           -   1           -   1
1           -   1           -   2
1           -   1           -   3
1           -   2           -   1
2           -   1           -   1
2           -   3           -   2
2           -   1           -   3
2           -   5           -   1
[and so on, there would be more registers for each id_Offer from Offer but I want to limit the example]

所以我总共有两个优惠,每个优惠都有一些。

表格提供如下所示:

Offer   -   business_name
1       -   business-1
2       -   business-1
3       -   business-1
4       -   business-1
5       -   business-2 
6       -   business-2 
7       -   business-2 
8       -   business-3

所以当我进行像

这样的查询时
select distinct id_offer, business_name, COUNT(*)
FROM Offer
GROUP BY business_name
Order by COUNT(*);

我得到的是业务-1我有4个优惠。

现在,如果我想考虑某些个人资料的优惠,我必须与我的三元关系进行联接。但即使我做了以下简单的事情

select distinct business_name
from Offer
INNER JOIN  ternary ON Offer.id_Offer = ternary.id_Offer
GROUP BY business_name
WHERE business_name =  'business-1'

无论我在小组中放置什么,或者如果我写不同,我都没有得到我想要的东西。现实情况是,对于business-1,我有4个优惠。现在三元只出现两个。因此,它应该为此名称返回2个唯一商品,而不按个人资料过滤。

但我获得了8个优惠,因为这是三元中出现的次数,id_Offer匹配的次数。

应该怎么做?如果我不需要过滤器,我可以单独查看“优惠”表。但是,如果我需要按id_skill或id_Profile过滤并想要返回business_name?

,该怎么办?

我见过像this这样的解决方案,但是我无法让它们工作,我不明白?是什么,如果MariaDB的工作方式相同,它是如何调用它的呢?从这个意义上讲,我无法找到有关它的信息,因为我不知道该操作是如何被调用的。当我尝试为我的数据构建查询时,我得到:

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '? ORDER BY COUNT(*) DESC' at line 1

但正如我所说,有点难以找到'?'作为...运营商?功能

2 个答案:

答案 0 :(得分:1)

有两种基本解决方案。

SELECT
  o.business_name,
  COUNT(DISTINCT o.id_offer)   AS unique_offers
FROM
  Offer     AS o
INNER JOIN
  ternary   AS t
    ON t.id_Offer = o.id_Offer
WHERE
      o.business_name = 'business-1'
  AND t.id_profile IN (1, 2, 3, 5)
GROUP BY
  o.business_name

这是最简单的写作和思考。但是,它也可能非常密集,因为您仍然将offer中的每一行连接到ternary中的4行 - 创建8行以汇总并处理DISTINCT

“更好”(在我看来)路由是过滤然后在子查询中聚合ternary表。

SELECT
  o.business_name,
  COUNT(*)         AS unique_offers
FROM
  Offer     AS o
INNER JOIN
(
  SELECT id_Offer
    FROM ternary
   WHERE id_profile IN (1, 2, 3, 5)
GROUP BY id_Offer
)
  AS t
    ON t.id_Offer = o.id_Offer
WHERE
  o.business_name = 'business-1'
GROUP BY
  o.business_name

这可确保t只有一行可用于任何给定的商品。这反过来意味着offer中的每一行只会加入t中的一行;没有重复。这反过来意味着不需要使用COUNT(DISTINCT)并减轻一些开销(通过将其移动到内部查询的GROUP BY

答案 1 :(得分:0)

您是说要查看特定商家的优惠,但是您想根据某些个人资料或技能限制这些优惠吗?

我们将查询结果限制在WHERE子句中。如果我们想要在另一个表格中查找数据,我们会使用INEXISTS。例如:

select *
from offer
where business_name = 'business-1'
and id_offer in
(
  select id_offer
  from ternary
  where id_profile = 1
    and id_skill = 2
);