根据值对行进行分组并插入另一个表

时间:2013-03-06 15:30:13

标签: mysql sql group-by

我有一张看起来像这样的表

Subject    Mark    Girls      Boys

Math        85      4          6
Math        86      1          3
Math        87      1          9
Math        92      2          9
Math        96      9          4
English     83      4          5
English     87      2          4 
English     91      2          3
English     99      4          1

我希望将这些数据插入到另一个看起来像

的表中
Subject    Range    Girls    Boys
Math       80-89    6         19
Math       90-99    11        13
English    80-89    6         9
English    90-99    6         4

假设只有两位数的分数,我的查询应该是什么来实现这一目标。 我尝试了一个非常幼稚的GROUP BYIF MARK like 1%但是失败了。

4 个答案:

答案 0 :(得分:1)

您可以使用CASE表达式来创建范围。如果您有更多范围,则会将它们添加到CASE

select subject,
  case 
    when mark >= 80 and mark <= 89 then '80-89'
    when mark >= 90 and mark <= 99 then '90-99'
  end `Range`,
  sum(girls) Girls,
  sum(boys) Boys
from yourtable
group by subject, case 
    when mark >= 80 and mark <= 89 then '80-89'
    when mark >= 90 and mark <= 99 then '90-99'
  end
order by subject

请参阅SQL Fiddle with Demo

如果您不想重复CASE中的GROUP BY,那么您可以使用子查询:

select subject, 
  `range`,
  sum(girls) girls,
  sum(boys) boys
from
(
  select subject,
    case 
      when mark >= 80 and mark <= 89 then '80-89'
      when mark >= 90 and mark <= 99 then '90-99'
    end `Range`,
    girls,
    boys
  from yourtable
) src
group by subject, `range`
order by subject

请参阅SQL Fiddle with Demo

我建议您考虑创建一个开头/结尾范围类似于此的表:

create table mark_ranges
(
  start_range int,
  end_range int
);

insert into mark_ranges values
(0, 9),
(10, 19),
(20, 29),
(30, 39),
(40, 49),
(50, 59),
(60, 69),
(70, 79),
(80, 89),
(90, 99);

创建表格后,通过加入表格可以轻松获得范围:

select subject,
  `range`,
  sum(girls) girls,
  sum(boys) boys
from
(
  select t.subject,
    concat(r.start_range, '-', r.end_range) `range`,
    t.girls,
    t.boys
  from yourtable t
  inner join mark_ranges r
    on t.mark >= r.start_range
    and t.mark <= r.end_range
) src
group by subject, `range`

请参阅SQL Fiddle with Demo

答案 1 :(得分:1)

这是一个自动定义标记范围并产生所需结果的查询:

SELECT 
  Subject, 
  CONCAT(MarkMin, '-', MarkMax),  
  (
    SELECT SUM(Girls) 
    FROM yourtable 
    WHERE Subject = Marks.Subject AND Mark >= MarkMin AND Mark <= MarkMax
  ) AS Girls,
  (
    SELECT SUM(Boys) 
    FROM yourtable 
    WHERE Subject = Marks.Subject AND Mark >= MarkMin AND Mark <= MarkMax
  ) AS Boys
FROM
(
SELECT
    Subject,
    ROUND(TRUNCATE(Mark/10,0),0) * 10 AS MarkMin,
    ROUND(TRUNCATE(Mark/10,0),0) * 10 + 9 AS MarkMax
FROM yourtable
GROUP BY Subject, MarkMin
) Marks;

Demo

答案 2 :(得分:0)

这是实现结果的TSQL:

select
    Subject,
    Range,
    Girls = Sum(Girls),
    Boys  = Sum(Boys)
from (
    values('80-89', 80, 89),
          ('90-99', 90, 99)
) T(Range, MinValue, MaxValue)
left join Data on Data.Mark between T.MinValue and T.MaxValue
group by Subject, Range

答案 3 :(得分:0)

以下是如何执行此操作的示例。我使用过SQL Server 2008 您可以使用您的确切问题修改查询,但我想知道。如果这样可以解决您的问题,请将答案标记为已接受。

-- sample: marks table
create table marks(sj varchar(200), mark  int, girl int, boy int)

-- insert some data
insert into marks values ('eng', 85, 2, 3)
insert into marks values ('eng', 86, 3, 4)
insert into marks values ('eng', 95, 4, 5)
insert into marks values ('eng', 95, 5, 6)

-- check data
select * from marks

-- create range table
create table marks_range(sj varchar(200), range varchar(200), girl int, boy int)

--now enter the ranges one by one

--80-89
insert into marks_range 
select sj, '80-89', SUM(girl), SUM (boy) from marks where mark < 90 and mark >= 80
group by sj

--90-99
insert into marks_range 
select sj, '90-99', SUM(girl), SUM (boy) from marks where mark < 100 and mark >= 90
group by sj

-- check result
select * from marks_range