【问题标题】:SQL to select common as well as remaining data using JOIN in MySQLSQL 在 MySQL 中使用 JOIN 选择常见数据和剩余数据
【发布时间】:2014-08-10 02:51:19
【问题描述】:

我有三个表:wi_district、wi_group 和 wi_training。我需要根据地区计算小组和培训。为此,我使用了以下 SQL;

  • SQL1
SELECT wi_district.dst_name, COUNT(grp_id) AS group_count, MAX(grp_created_date) as grp_created_date
来自 wi_group
INNER JOIN wi_district ON wi_district.dst_id=wi_group.grp_dst_id AND wi_group.grp_deleted=0 AND wi_group.grp_type IN (3)
按 wi_district.dst_name 分组

每个区的查询计数组。同样,

  • SQL2
SELECT wi_district.dst_name, COUNT(trn_id) AS training_count, MAX(trn_created_date) as trn_created_date
来自 wi_training
INNER JOIN wi_district ON wi_district.dst_id=wi_training.dst_id AND wi_training.trn_deleted=0 AND wi_training.trn_beneficiary_type IN (-1,2,8,9,10)
按 wi_district.dst_name 分组

查询计算每个地区的培训。现在我需要将所有从 SQL1 和 SQL2 得到的结果结合起来,得到结果形式为

dst_name ||组数 || grp_created_date ||培训计数 || trn_created_date

问题是每当我使用 SQL1 LEFT JOIN SQL2 时,它都会显示与 SQL1 相关的结果,而 SQL2 的结果无法获得,反之亦然。请帮我解决 MySQL 中的这个问题

【问题讨论】:

  • 那么不要使用左连接。 left join 是“左表的所有匹配记录,右表的任何匹配记录”。如果您需要两个表中的所有记录,则需要外连接。

标签: php mysql sql join


【解决方案1】:

我认为你可以加入过滤表,然后按区名分组。像这样:

SELECT dist.dst_name AS dst_name,
COUNT(grp.grp_id) AS group_count, MAX(grp.grp_created_date) AS grp_created_date,
COUNT(trn.trn_id) AS training_count, MAX(trn.trn_created_date) AS trn_created_date 
FROM wi_district AS dist
LEFT JOIN (
  SELECT dst_id, trn_id, trn_created_date
  FROM wi_training
  WHERE trn_deleted=0
    AND trn_beneficiary_type IN (-1,2,8,9,10)
) AS trn ON trn.dst_id=dist.dst_id
LEFT JOIN (
  SELECT grp_dst_id, grp_id, grp_created_date
  FROM wi_group
  WHERE grp_deleted=0
    AND grp_type IN (3)
) AS grp ON grp.grp_dst_id = dist.dst_id
GROUP BY dist.dst_name

【讨论】:

    【解决方案2】:

    为什么要使用像 dst_name 这样的名称?最好把全名写出来,几个月后你也会明白它的意思。

    无论如何,这个查询应该可以解决问题

    select d.dst_name as district
    ,      count(distinct g.grp_id) as group_count
    ,      max(grp_created_date) as group_created_date 
    ,      count(distinct trn_id) as training_count
    ,      max(trn_created_date) as trn_created_date 
    from   wi_district d
    left join wi_group g on  d.dst_id = g.grp_dst_id
                         and g.grp_deleted = 0 
                         and g.grp_type in (3)
    left join wi_training t on  d.dst_id = t.dst_id
                            and t.trn_deleted = 0
                            and t.trn_beneficiary_type IN (-1,2,8,9,10)
    group by d.dst_name
    

    【讨论】:

    • 不客气。只需确保在 count() 中有 DISTINCT 关键字,否则组数将乘以每个地区的培训。
    【解决方案3】:

    您需要从分组表中驱动它。像这样。

    SELECT  D.dst_name,  COUNT(grp_id) AS group_count, MAX(grp_created_date) as grp_created_date, COUNT(trn_id) AS training_count, MAX(trn_created_date) as trn_created_date 
    FROM    wi_district D
    LEFT JOIN wi_group G ON D.dst_id = G.grp_dst_id AND G.grp_deleted=0 AND G.grp_type IN (3)
    LEFT JOIN wi_training T ON  D.dst_id = T.dst_id AND T.trn_deleted=0 AND T.trn_beneficiary_type IN (-1,2,8,9,10)
    GROUP BY wi_district.dst_name
    

    如果您只想要任一表上存在的行,请添加一个子句:

    WHERE NOT G.grp_dst_id IS NULL OR NOT D.dst_id IS NULL
    

    【讨论】:

    • 如果是答案,请将其标记为答案 :)
    猜你喜欢
    • 2018-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-29
    • 1970-01-01
    相关资源
    最近更新 更多