在MySQL中如何从1行查询2列?

时间:2014-06-04 02:09:29

标签: mysql sql join union

在MySQL表卡中,每次将信用卡余额从一张卡转移到另一张卡时,ToCard有1行。

create table cardToCard (
  id int, 
  dt date,
  card_from int,
  card_to int,
  amount decimal(6,2),
  primary key (id)
);

insert into cardToCard values (1, '2014-01-01', 100, 101, 200.00);
insert into cardToCard values (2, '2014-01-01', 101, 102, 200.00);
insert into cardToCard values (3, '2014-01-01', 102, 103, 200.00);
insert into cardToCard values (4, '2014-01-01', 103, 104, 200.00);
insert into cardToCard values (5, '2014-01-01', 104, 100, 200.00);
insert into cardToCard values (6, '2014-01-01', 99, 104, 200.00);

查询哪张卡已被使用过3次或更多次。

select card, count(*) 'count'
from
  (
  select card_from 'card', dt
  from cardtocard
  union all
  select card_to 'card', dt
  from cardtocard
  ) d
group by card
having count >= 3

结果是正确的。问题是将此写为自联接会更有效吗?

http://sqlfiddle.com/#!2/420e72/1

1 个答案:

答案 0 :(得分:2)

编写此查询的最有效方法可能是从卡片列表开始,然后执行:

select c.card,
       ((select count(*) from cardTocard ctc where ctc.card_from = c.card) +
        (select count(*) from cardTocard ctc where ctc.card_to = c.card)
       ) as cnt
from cards c
having cnt >= 3;

然后,您需要两个索引:cardTocard(card_from)cardTocard(card_to)

这应该使用聚合索引,这通常比文件排序快。

编辑:

使用您正在使用的结构,在子查询和外部查询中进行聚合会更快:

select card, sum(cnt) as cnt
from ((select card_from as car, count(*) as cnt
       from cardtocard
       group by card_from
      ) union all
      (select card_to as card, count(*) as cnt
       from cardtocard
       group by card_to
      )
     ) d
group by card
having count >= 3;

这可以更快,因为子查询的数据量小于union将它们放在一起。