MYSQL:通过不同的组查找序列中的缺失值

时间:2016-05-24 14:18:31

标签: mysql

Hy,请帮忙,我有12个项目的完整序列,我通过2个不同的组(12345和54321)识别这些项目。现在,我需要确定项目“12345”的第一个序列在4处停止并在10处重新开始。这样的事情:

我有这张桌子:

------------------
|seq  |partNumber|
------------------
| 1   |  12345   |
| 2   |  12345   |
| 3   |  12345   |
| 4   |  12345   |
| 10  |  12345   |
| 11  |  12345   |
| 12  |  12345   |
| 5   |  54321   |
| 6   |  54321   |
| 7   |  54321   |
| 8   |  54321   |
| 9   |  54321   |
------------------

我需要找到这个结果:

------------
|Start|Stop|
------------
|  5  |  9 | (partnumber:12345)
------------

我使用的查询:

select start, stop from (
 select m.partNumber + 1 as start,
    (select min(partNumber) - 1 from seq as x where x.partNumber > m.partNumber) as stop
  from seq as m
    left outer join seq as r on m.partNumber = r.partNumber - 1 where r.partNumber is null) as x
where stop is not null;

但是,这个查询给了我这个结果:

------------
|Start|Stop|
------------
|  9  |  9 | (partnumber:12345)
------------

最终结果: 我想确定序列中的“12345”开始于1个结束,4个(休息)重启,10个结束12,我有一个5到9的间隙。“54321”的另一个序列从5个结束开始,9,这里我不要没有差距。

1 个答案:

答案 0 :(得分:0)

这是结构化查询语言的结构化部分的一个很好的应用程序。

我猜你永远不会有seq小于零或大于仲裁值15624的值。这个猜测很重要:我们需要一个包含该范围内所有基数的表来使缺失数检测起作用。

这是一张表

SELECT A.N + 5*(B.N + 5*(C.N + 5*(D.N + 5*(E.N + 5*(F.N))))) AS seq
  FROM (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS A
  JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS B
  JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS C
  JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS D
  JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS E
  JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS F

(如果您使用的是MariaDB,则可以使用Sequenceseq_0_to_15624代替这一部分SQL代码。)

接下来,您需要一种方法来找出每个部件号的seq的最低值和最高值。你是这样做的。

       SELECT partNumber, MIN(seq) minSeq, MAX(seq) maxSeq
         FROM seq
        GROUP BY partNumber

接下来,您需要生成一个表格,显示每个部件编号从最小到最大的所有可能序列号:

SELECT cardinals.seq, r.partNumber
  FROM (
        SELECT A.N + 5*(B.N + 5*(C.N + 5*(D.N + 5*(E.N + 5*(F.N))))) AS seq  
          FROM (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS A
          JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS B
         JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS C
         JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS D
         JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS E
         JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS F
       ) cardinals
  JOIN (
         SELECT partNumber, MIN(seq) minSeq, MAX(seq) maxSeq
           FROM seq
          GROUP BY partNumber
   ) r ON cardinals.seq >= r.minSeq AND cardinals.seq <= r.maxSeq

最后,您可以将其连接到原始表格,然后WHERE val IS NULL找到您丢失的序列号。

SELECT cardinals.seq, r.partNumber
  FROM (
        SELECT A.N + 5*(B.N + 5*(C.N + 5*(D.N + 5*(E.N + 5*(F.N))))) AS seq  
          FROM (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS A
          JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS B
         JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS C
         JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS D
         JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS E
         JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS F
           ) cardinals
  JOIN (
             SELECT partNumber, MIN(seq) minSeq, MAX(seq) maxSeq
               FROM seq
              GROUP BY partNumber
       ) r ON cardinals.seq >= r.minSeq AND cardinals.seq <= r.maxSeq
  LEFT JOIN seq ON cardinals.seq = seq.seq AND r.PartNumber = seq.partNumber
 WHERE seq.seq IS NULL