3

在 SQL 中,我有下面的表 t_test:

emp_code | period_month | 公司代码  
NIK001 | 01 | Α
NIK001 | 02 | Α
NIK001 | 03 | Α
NIK001 | 04 | Α
NIK001 | 05 | Α
NIK001 | 06 | 测试版
NIK001 | 07 | 测试版
NIK001 | 08 | 测试版
NIK001 | 09 | 测试版
NIK001 | 10 | Α
NIK001 | 11 | Α
NIK001 | 12 | Α

我想查询以下结果:

emp_code | 公司代码 | 从_月 | to_month
--------------------------------------------------
NIK001 | 阿尔法 | 01 | 05
NIK001 | 测试版 | 06 | 09
NIK001 | 阿尔法 | 10 | 12
4

3 回答 3

1

您可以使用 MySQL 变量。例如:

SET @ttt = 0;

SELECT
    @ttt := IF(
        `company_code`=(SELECT `company_code` FROM `range` r2 WHERE r2.`period_month`<r1.`period_month` ORDER BY `period_month` DESC LIMIT 1), 
        @ttt,
        @ttt+1) iter,
`period_month`,
`company_code`
FROM `range` r1
WHERE emp_code = 'NIK001'
ORDER BY period_month ASC;

根据我的测试数据,这给了我:

iter period_month company_code
1    1            Alpha
1    2            Alpha
1    3            Alpha
2    4            Beta
2    5            Beta
2    6            Beta
3    7            Alpha
3    8            Alpha
3    9            Alpha
3    10           Alpha

这个想法是在每一行上检查当前company_code是否等于先前记录的。如果不同,则增加变量。

这是一个进步。但是如何对行进行分组?您不能直接对它们进行分组,但您需要用第二个查询包装该查询。

SET @ttt = 0;

SELECT `company_code`,MIN(`period_month`),MAX(`period_month`)
FROM
(    SELECT
        @ttt := IF(
            `company_code`=(SELECT `company_code` FROM `range` r2 WHERE r2.`period_month`<r1.`period_month` ORDER BY `period_month` DESC LIMIT 1), 
            @ttt,
            @ttt+1) iter,
    `period_month`,
    `company_code`
    FROM `range` r1
    WHERE emp_code = 'NIK001'
    ORDER BY period_month ASC
    ) subreq
GROUP BY iter
;

那是在外部查询中使用内部查询的结果。这给了我,我的测试数据,

company_code MIN(`period_month`) MAX(`period_month`)
Alpha        1                   3
Beta         4                   6
Alpha        7                   10

如果您需要限制行的选择,请在内部查询的 where 子句中执行此操作,否则整个数据库将在每次查询时加载到内存中。另一个问题是内部查询将前一条记录获取为“具有最接近下限的记录period_month。因此,您不能按除 之外的任何内容对内部查询进行period_month ASC排序。如果需要,您仍然可以对外部查询中的内容进行排序。

最后,如果mysql_query出于某种原因使用旧界面,则需要将该SET行放在单独的查询中,因为它一次只能处理一个查询。

mysql_query("SET @ttt = 0;");

$rs=mysql_query("SELECT `company_code`,MIN(`period_month`),MAX(`period_month`)
FROM
(    SELECT
        @ttt := IF(
            `company_code`=(SELECT `company_code` FROM `range` r2 WHERE r2.`period_month`<r1.`period_month` ORDER BY `period_month` DESC LIMIT 1), 
            @ttt,
            @ttt+1) iter,
    `period_month`,
    `company_code`
FROM `range` r1) subreq
    GROUP BY iter
;");

不确定这种方法在扩展到大型数据库时效果如何,但它确实有效。也许有一个“好”的方法。只要确保您不会在查询中意外弄乱某些东西,以防您不完全理解它。:)

于 2011-04-17T04:53:00.623 回答
1

这让我害怕得发抖,但它确实输出了你所追求的近似值:

    select w.emp_code, w.company_code, w.period_month from_month,
(select min(convert(u.period_month,unsigned))-1 from t_test u where u.emp_code=w.emp_Code and convert(u.period_month,signed)>convert(w.period_month,signed) and u.company_code<>w.company_code) to_month
 from 
(
select * from
(
select y.emp_code, y.period_month, y.company_code,
(select x.company_code from t_test x where x.emp_code=y.emp_code and convert(x.period_month,unsigned)<convert(y.period_month,unsigned) order by convert(x.period_month,unsigned) desc limit 1) previous_company_code
 from t_test y
) z
where company_code<>previous_company_code or previous_company_code is null
) w

但是,我只是出于好奇而尝试了这个。您不应该在生产环境中真正依赖类似的东西。我认为简单的 SQL 查询不适合您的问题。我会去别处看看。

编辑:基于下表:

CREATE TABLE `t_test` (
  `emp_code` varchar(50) DEFAULT NULL,
  `period_month` varchar(2) DEFAULT NULL,
  `company_code` varchar(50) DEFAULT NULL
);

填充以下 INSERT 语句:

INSERT INTO `t_test` (`emp_code`,`period_month`,`company_code`)
VALUES
    ('NIK001', '01', 'ALPHA'),
    ('NIK001', '02', 'ALPHA'),
    ('NIK001', '03', 'ALPHA'),
    ('NIK001', '04', 'ALPHA'),
    ('NIK001', '05', 'ALPHA'),
    ('NIK001', '06', 'BETA'),
    ('NIK001', '07', 'BETA'),
    ('NIK001', '08', 'BETA'),
    ('NIK001', '09', 'BETA'),
    ('NIK001', '10', 'ALPHA'),
    ('NIK001', '11', 'ALPHA'),
    ('NIK001', '12', 'ALPHA');
于 2011-04-17T03:40:19.883 回答
0

@magma:非常感谢答案。好工作!谢谢..

我只是做了一点修改,所以 from_month 和 to_month 永远不会得到 NULL 值。

为了加快执行查询的速度,我使用会话创建临时表来存储查询结果,并使用临时数据生成报告

选择
  w.emp_code, w.company_code, w.period_month from_month,
  平板电脑(
    如果空(
    如果空(
      (选择分钟(u.period_month)-1
        从 t_test 你
        其中(u.emp_code = w.emp_code)
        和(u.period_month > w.period_month)
        和(u.company_code w.company_code)
      ),( 选择最大值(v.period_month)
          从 t_test v
          在哪里
          (v.emp_code=w.emp_code)
          和(v.period_month > w.period_month)
          和 (v.company_code = w.company_code)
         )
    ),( 选择最大值(z.period_month)
          从 t_test z
          在哪里
          (z.emp_code=w.emp_code)
          和(z.period_month = w.period_month)
          和 (z.company_code = w.company_code)
         )
    ),2,'0'
  ) 作为 to_month
从
  ( 选择 *
    从
    (
      选择
        y.emp_code, y.company_code, y.period_month,
        (选择 x.company_code
          从 t_test x
          在哪里
          (x.emp_code = y.emp_code)
          和(x.period_month previous_company_code)
  或(previous_company_code 为空)
  ) w
于 2011-04-19T16:32:48.717 回答