MySQL多连接查询

时间:2017-06-20 21:36:46

标签: php mysql sql database

我有多个表我试图从单个查询中获取数据。我似乎接近解决方案,但似乎无法获得我期待的数据结果。

我的表格示例如下(字段已被截断):

表c
ID
命名
缩写

表mr(关系表通过ID将表c和m连接在一起)
ID
c.id
m.id

表m
ID

表cnt
ID
c.id

表cmp
ID
cnt.id
活性

我想要的是来自C的所有字段,来自M的所有字段,其中m.id = c.id,所有活动的(active = 1)id来自CMP,与cnt.id匹配。

我最近的查询(经过几十次迭代)是:

SELECT c.id AS id
    , c.name AS name
    , c.abbreviation AS abbr
    , c.active AS active
    , c.last_modified AS last_modified
    , c.modified_by AS modified_by
    , mr.media_id
    , mr.related_object_table
    , mr.related_object_id
    , m.orig_name AS img_name
    , m.unique_name AS img_slug
    , m.file_type AS confed_file_type
    , m.file_size AS file_size
    , COUNT('cmp.id') AS comps
FROM confederations AS c
LEFT JOIN media_relationships AS mr 
ON mr.related_object_id = c.id 
AND mr.related_object_table = 'confederations'
LEFT JOIN media AS m 
ON m.id = mr.media_id
INNER JOIN countries AS cnt
ON cnt.confederations_id = c.id
INNER JOIN competitions AS cmp
ON cmp.countries_id = cnt.id 
AND cmp.active = 1;

我不熟练加入。

基本上,我期待的结果是:对于每个联邦(表C),我想要联盟名称,缩写,活动状态(活动),最后修改日期,修改者;从媒体关系表(表MR)我想要与该联盟关联的图像ID,以便我可以使用该ID从媒体表(M)中获取联盟主图像的图像名称和图像slug。

现在我还想要一个特定联邦的比赛总数(表格CMP)。比赛以国家ID存储,该国家ID与国家表(表CNT)中国家的主键ID相关联。表CNT中的每个国家/地区都有一个联盟ID。因此,为了获得每个联合会的比赛总数,我正在尝试“#39;为了通过表CNT中的CONFEDERATIONS_ID获得各自国家联盟内的所有国家,然后我要联盟的联盟选择表CMP中的所有比赛,并从该联盟的国家ID组中匹配COUNTRIES_ID。 (此时我觉得我很困惑自己如何得到我想要的东西)

不知何故,我获得了正确的比赛数量,但我得到了重复的联合会作为结果。举例来说,我得到类似的东西(假设我有3个不同的联合会,分别有2个,1个和3个比赛):

Competitions 1 : name 1 | abbreviation 1 | image 1 | total competitions = 2;
Competitions 1 : name 1 | abbreviation 1 | image 1 | total competitions = 1;
Competitions 1 : name 1 | abbreviation 1 | image 1 | total competitions = 3

我做错了什么?

2 个答案:

答案 0 :(得分:0)

汇总时,您需要分组。

也许这与你正在寻找的很接近:

SELECT c.id AS id
     , c.name AS name
     , c.abbreviation AS abbr
     , m.orig_name AS img_name
     , SUM('cmp.id') AS comps
FROM confederations AS c
LEFT JOIN media_relationships AS mr 
   ON mr.related_object_id = c.id
   AND mr.related_object_table = 'confederations'
LEFT JOIN media AS m 
   ON m.id = mr.media_id
INNER JOIN countries AS cnt
   ON cnt.confederations_id = c.id
INNER JOIN competitions AS cmp
   ON cmp.countries_id = cnt.id 
   AND cmp.active = 1
GROUP BY  c.id AS id
        , c.name AS name
        , c.abbreviation AS abbr
        , m.orig_name AS img_name

答案 1 :(得分:0)

通过反复试验,我实际上已经解决了这个问题。我回来发布我的回答并看到了Degan的答案,尽管它的写法与我的不同,但我认为与我最终的结果非常接近:

SELECT
    cnf.id AS confed_id, cnf.name AS confed_name, cnf.abbreviation AS 
    confed_abbr, cnf.active AS confed_active, cnf.modified_by AS 
    confed_mod_by, cnf.last_modified AS confed_last_mod,
    COUNT(cnt.id) AS total_countries,
    COUNT(cmp.id) AS total_comps,
    mr.media_id, mr.related_object_table, mr.related_object_id, 
    mr.primary_img,
    m.orig_name AS img_name, m.unique_name AS img_slug, m.file_type AS file_type
FROM confederations AS cnf
LEFT JOIN media_relationships AS mr
ON mr.related_object_id = cnf.id AND mr.related_object_table = 'confederations'
LEFT JOIN media AS m
ON m.id = mr.media_id
LEFT JOIN countries AS cnt
ON cnt.confederations_id = cnf.id AND cnt.active = 1
LEFT JOIN competitions AS cmp
ON cmp.countries_id = cnt.id AND cmp.active = 1
GROUP BY cnf.id

所以farthis似乎给了我可以使用的结果。我不确定我为所有联接选择Left Join是否实际上给了我所需要的一切(它看起来很简单)以及一旦表变大就会省略/添加记录。如果有人可以指出我的查询中的问题以及我选择使用Left Join而不是像Degan那样使用LEFT和INNER JOIN的组合,那将会有所帮助。