两个子查询上的Mysql内连接返回重复的行

时间:2012-08-10 11:42:48

标签: mysql

我们有一张像

这样的表格
Table1(Contract_id, name, address, contact_no)

和另一张表,

Table2(Contract_id, approver, owner, authority)

示例数据:

mysql> select * from Table1;
+-------------+-------+---------+------------+
| contract_id | owner | address | contact_no |
+-------------+-------+---------+------------+
|       11111 | XXX   | Madurai | 897161     |
|       12456 | XYZ   | Madras  | 897161     |
|       11111 | XYZ   | Madras  | 897161     |
+-------------+-------+---------+------------+
3 rows in set (0.00 sec)

mysql> select * from Table2;
+-------------+----------+
| contract_id | approver |
+-------------+----------+
|       11111 | YZX      |
|       11112 | YYY      |
+-------------+----------+
2 rows in set (0.00 sec)

我编写了一个查询来获取所有contract_ids和匹配数据,例如

“与所有者签订所有合同,如'X',地址如”Mad“和approver ='YZX'”

select contract_id,owner,address,approver 
from 
(
    select *
    from Table1 
    where owner like '%X%' 
    and address like '%Mad%'
) t1 
inner join 
(
    select * 
    from Table2 
    where approver = 'YZX'
) t2 using (contract_id);

正确返回结果。但问题是左表有两个匹配的行,右表只有一个匹配的行。因此右表中的行重复两次。

> +-------------+---------------+-----------+-------------+
> |contract_id  |  owner        | address   | approver    |
> +-------------+---------------+-----------+-------------+
> |11111        | XXX           | Madurai   | YZX         |
> +-------------+---------------+-----------+-------------+
> |11111        | XYZ           | Madras    | YZX         | 
> +-------------+---------------+-----------+-------------+

批准者值重复两次。我能以某种方式避免这个mysql本身吗? 我想要第二行的批准者列的空值。

编辑1:

我编辑了我的查询,最后通过审批人

select contract_id,owner,address,approver 
from 
(
    select contract_id
    from Table1 
    where owner like '%X%' 
    and address like '%Mad%'
) t1 
inner join 
(
    select contract_id 
    from Table2 
    where approver = 'YZX'
) t2 using (contract_id) group by approver;

现在结果变得如此,

> +-------------+---------------+-----------+-------------+
> |contract_id  |  owner        | address   | approver    |
> +-------------+---------------+-----------+-------------+
> |11111        | XYZ           | Madurai   | YZX         |
> +-------------+---------------+-----------+-------------+

第二个现在失踪了。我也想要那个。

编辑2:添加了示例数据和确切查询。

编辑3:我希望结果格式如下,

> +-------------+---------------+-----------+-------------+
> |contract_id  |  owner        | address   | approver    |
> +-------------+---------------+-----------+-------------+
> |11111        | XXX           | Madurai   | YZX         |
> +-------------+---------------+-----------+-------------+
> |11111        | XYZ           | Madras    | NULL        | 
> +-------------+---------------+-----------+-------------+

编辑4:我实现了我想要的东西。以下是我使用的查询。

create temporary table table1 select * 
from 
(
    select *
    from Table1 
    where owner like '%X%' 
    and address like '%Mad%'
) t1 
inner join 
(
    select * 
    from Table2 
    where approver = 'YZX'
) t2 using (contract_id) limit 1;

和查询,

insert into table1 select contract_id, IF((select count(*) from table1 where owner = t.owner and contract_id = t.contract_id) > 0, NULL, t.contract_id),IF((select count(*) from table1 where address = t.adress and contract_id = t.contract_id) > 0, NULL, t.contract_id),IF((select count(*) from table1 where approver = t.approver and contract_id = t.contract_id) > 0, NULL, t.contract_id)
from 
((
    select *
    from Table1 
    where owner like '%X%' 
    and address like '%Mad%'
) t1 
inner join 
(
    select * 
    from Table2 
    where approver = 'YZX'
) t2 using (contract_id)) t;  

3 个答案:

答案 0 :(得分:3)

要清楚数据不是重复的。由于您要加入contract_id上的两个表,并且相同的合同ID与两个记录相关联,因此您将使批准者出现两次。

mysql> select * from Table1;
+-------------+-------+---------+------------+
| contract_id | owner | address | contact_no |
+-------------+-------+---------+------------+
|       11111 | XXX   | Madurai | 897161     | -- contract_id 11111
|       12456 | XYZ   | Madras  | 897161     |
|       11111 | XYZ   | Madras  | 897161     | -- contract_id 11111
+-------------+-------+---------+------------+
3 rows in set (0.00 sec)

mysql> select * from Table2;
+-------------+----------+
| contract_id | approver |
+-------------+----------+
|       11111 | YZX      | -- contract_id 11111
|       11112 | YYY      |
+-------------+----------+
2 rows in set (0.00 sec)

因此,结果将始终是来自table1的两条记录和来自第二组的一条记录approver = 'YZX'

另一方面,我可能会考虑将查询重写为以下内容:

select t1.contract_id, t1.owner, t1.address, t2.approver 
from table1 t1
inner join table2 t2
  on t1.contract_id = t2.contract_id
where t1.owner like '%X%'
  and t1.address like '%Mad%'
  and t2.approver = 'YZX'

根据您的评论,我开始认为您可能需要LEFT JOIN

select t1.contract_id, t1.owner, t1.address, t2.approver 
from table1 t1
left join table2 t2
  on t1.contract_id = t2.contract_id
  and t2.approver = 'YZX'
where t1.owner like '%X%'
  and t1.address like '%Mad%'

请参阅SQL Fiddle with Demo

编辑2:没有简单的方法可以强制它为其他字段使用null。您可以尝试使用rownumber来获得结果:

select x.contract_id, 
  x.owner,
  x.address,
  case when (@rownum:=@rownum+1 = 1) then x.approver else null end approver
from 
(
  select t1.contract_id, t1.owner, t1.address, t2.approver
  from table1 t1
  inner join table2 t2
    on t1.contract_id = t2.contract_id
    and t2.approver = 'YZX'
  where t1.owner like '%X%'
    and t1.address like '%Mad%'
) x, (SELECT @rownum:=0) r

请参阅SQL Fiddle with Demo

答案 1 :(得分:1)

使用DISTINCT子句来避免重复:

SELECT contract_id,owner,address,approver
from (select DISTINCT contract_id
      from Table1 where owner like '%X%' and address like '%Mad%'
     ) t1
     inner join (select contract_id from Table2 where approver = 'YZX') t2
        using (contract_id);

答案 2 :(得分:1)

它没有重复,它正好显示它应该显示的内容。

如果您解释了要显示哪条记录以及要从结果集中排除哪条记录的标准,那么我们可以选择一些符合您要求的记录。

您在第一次更新时提供的查询在语法上可能在MySQL上有效(它不适用于其他数据库)但是语义上的胡言乱语 - 您是如何告诉DBMS您确实要排除owner = XXX的情况?或地址=马德拉斯?