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

Mysql 如何在保持唯一行的同时进行内部联接,mysql,sql,join,mariadb,Mysql,Sql,Join,Mariadb,我有一个三元关系,在这个关系中,我建立了工作机会、个人资料和技能之间的关系。例如,三元关系表称为三元,将三个表的ID作为主键。它可能看起来像这样: id_Offer - id_Profile - id_Skill 1 - 1 - 1 1 - 1 - 2 1 - 1 - 3 1 - 2 - 1

我有一个三元关系,在这个关系中,我建立了工作机会、个人资料和技能之间的关系。例如,三元关系表称为
三元
,将三个表的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
因此,我总共有2个报价,每个报价中都有一些配置文件

餐桌上的优惠如下所示:

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(*);
我是为生意而买的,我有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_报价是匹配的

如何做到这一点?如果我不需要过滤器,我只需单独查看报价表即可。但是,如果我需要按id\u技能或id\u配置文件进行筛选,并希望返回业务名称,该怎么办

我见过这样的解决方案,但我不能让它们工作,我不明白
是什么,如何调用它来了解更多信息,如果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

但正如我所说的,很难把“?”作为一个。。。操作人员功能?

有两种基本解决方案

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
中的每一行连接到
trialum
中的4行-创建8行以通过
DISTINCT
进行聚合和处理

“更好”(在我看来)的方法是过滤然后在子查询中聚合
三元

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)
,并减轻了一些开销(通过将其移动到内部查询的
分组By
)。

您是说您想查看特定业务的报价,但您想根据特定的配置文件或技能来限制这些报价吗

我们在
WHERE
子句中限制查询结果。如果我们想在另一个表中查找数据,可以使用
中的
存在的
。例如:

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
);

示例数据列与查询列不匹配。您很少不会将GROUP BY与SELECT DISTINCT组合,因为GROUP BY会消除重复项。此外,在没有任何聚合函数的情况下,您永远不需要使用GROUP BY子句。@jarlh NOVER或NOVER-which?@草莓,可以偶尔组合一次,但很少。如果我从配置文件中删除过滤器,我会得到我应该得到的号码。太好了!!现在我有一个问题,这可能与我的数据有关,但是。。。为什么如果我一个接一个地按每个配置文件过滤,计数的总和要比我在子查询中不按配置文件过滤,只按业务名称过滤时的总和大(意思是:假设我想要所有配置文件中的报价。如果我删除配置文件的过滤器,我应该得到正确的结果?但数字不匹配)@monkeyintern-因为
id\u offer==1
包含在配置文件1和2中。而
id\u offer==2
包含在配置文件1、3和5中。所以,不,它们不应该相加
Profile\u 1的报价
(2)+
Profile\u 2的报价
(1)将高于
Profile\u 1或\u 2的报价
(2)?我没有应用正确的语法。我们的想法是做同样的事情,过滤然后聚合,但是一旦它被过滤,除此之外,我做了几个连接。在这种情况下,我应该如何给表格贴上标签?@monkeyintern这还不够,我建议提出一个新的问题,提供完整的细节。