Mysql 53 | 53 |[NULL]| 54 | 54 |[零]| 55 | 55 |[零]| 56| 56| 56| 57 |[NULL]|[NULL]| 58 |[NULL]|[NULL]| {截取重复的空值} 74 |[NULL]|[NULL]

Mysql 53 | 53 |[NULL]| 54 | 54 |[零]| 55 | 55 |[零]| 56| 56| 56| 57 |[NULL]|[NULL]| 58 |[NULL]|[NULL]| {截取重复的空值} 74 |[NULL]|[NULL],mysql,sql,Mysql,Sql,53 | 53 |[NULL]| 54 | 54 |[零]| 55 | 55 |[零]| 56| 56| 56| 57 |[NULL]|[NULL]| 58 |[NULL]|[NULL]| {截取重复的空值} 74 |[NULL]|[NULL]| 75 |[NULL]|[NULL]| 76| 76| 76| 77 |[NULL]|[NULL]| 78 |[NULL]|[NULL]| {截取重复的空值} 86 |[NULL]|[NULL]| 87 |[NULL]|[NULL

53 | 53 |[NULL]| 54 | 54 |[零]| 55 | 55 |[零]| 56| 56| 56| 57 |[NULL]|[NULL]| 58 |[NULL]|[NULL]| {截取重复的空值} 74 |[NULL]|[NULL]| 75 |[NULL]|[NULL]| 76| 76| 76| 77 |[NULL]|[NULL]| 78 |[NULL]|[NULL]| {截取重复的空值} 86 |[NULL]|[NULL]| 87 |[NULL]|[NULL]| 88| 88| 88| 89 |[NULL]|[NULL]| 90 |[NULL]|[NULL]| {截取重复的空值} 98 |[NULL]|[NULL]| 99 |[NULL]|[NULL]| 100| 100| 100| */
哪个版本的MySQL?@Nick
版本14.16发行版5.2.4-MariaDB-rp
使用子查询而不是左连接:
选择1作为id union all select 2 union all select…
@juergend,在我的真实情况下,我有>3000 id。我认为使用
select 1 union…
不是一个好的解决方案!此方法假定数字列表始终是连续的,没有gaps@RaymondNijland好的,我用
MIN
编辑我的答案,
MAX
函数为开始和结束值,然后执行CTE递归更新将不允许在数字列表中使用间隙。此方法还假设数字列表中没有间隙。您不认为如果数字列表增加到1000,仅使用Select或最多10000就几乎不可能生成一个列表,在任何情况下,我很确定它都会生成。@AnkitBajpai true给我一些时间来找出一个更具动态性的列表method@RaymondNijland,谢谢你的回答。尽管如此,我不喜欢使用这个
SELECT。。UNION
语句,但我成功地创建了查询动态的这一部分(使用了Sublime文本编辑工具:P),现在我得到了我想要的。@AnkitBajpai“你不认为如果数字列表增加到1000,仅使用Select或最多10000就几乎不可能生成一个列表,我很确定这一点。”我已经发布了一个升级,使它更dynamic@HamzaAbdaoui我已经发布了一个升级,使它更具动态性
+--------+
| tab_id |
+--------+
|    1   |
|    2   |
|   ...  |
|   50   |
|   56   |
|   100  |
+--------+
create table my_tab(
    tab_id int
);

insert into my_tab values (1);
insert into my_tab values (2);
insert into my_tab values (3);
insert into my_tab values (4);
insert into my_tab values (5);
insert into my_tab values (9);
insert into my_tab values (10);
insert into my_tab values (20);
WITH RECURSIVE  cte AS (
  SELECT MIN(tab_id) fromVal,MAX(tab_id) toVal
  FROM my_tab
  UNION ALL
  SELECT (fromVal+1),toVal
  FROM cte
  WHERE fromVal < toVal
)
SELECT fromVal
FROM cte c
WHERE NOT exists
(
  SELECT 1 
  FROM my_tab t1
  WHERE t1.tab_id = c.fromVal
);

| fromVal |
| ------- |
| 6       |
| 7       |
| 8       |
| 11      |
| 12      |
| 13      |
| 14      |
| 15      |
| 16      |
| 17      |
| 18      |
| 19      |
select n+1 from my_tab
right outer join
(select (d1.n*10 + d2.n) n from (select 1 as n union all select 2 union all select 3 union all select 4 union all select 5 union all
  select 6 union all select 7 union all select 8 union all select 9 union all select 0
 ) d1 cross join
 (select 1 as n union all select 2 union all select 3 union all select 4 union all select 5 union all
  select 6 union all select 7 union all select 8 union all select 9 union all select 0
 ) d2) temp_num
on tab_id = n+1
where tab_id is null
order by n
| number |
|--------|
|      3 |
|      4 |
|     51 |
|     52 |
|     53 |
|     54 |
|     55 | 
SELECT  
 number_list.number
FROM (

  SELECT 
   1 AS number
  UNION 
   SELECT 
     2 AS number   
  UNION
  SELECT 
   3 AS number
  UNION 
  SELECT 
     4 AS number 
  # ...
  # ...
  UNION
  SELECT 
    50 AS number
  UNION 
  SELECT 
    51 AS number 
  UNION
  SELECT 
    52 AS number
  UNION 
  SELECT 
    53 AS number 
  UNION
  SELECT 
    54 AS number
  UNION 
  SELECT 
    55 AS number 
  UNION
  SELECT 
    56 AS number
  UNION 
  # ...
  # ...  
  SELECT 
    100 AS number 

) AS number_list
LEFT JOIN 
 Table1
ON
 number_list.number = Table1.tab_id
WHERE
  Table1.tab_id IS NULL
| number |
|--------|
|      3 |
|      4 |
|     51 |
|     52 |
|     53 |
|     54 |
|     55 |
SELECT 
 (@row_number := @row_number + 1) AS row_number
FROM (
 SELECT 1 AS n UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 10
) AS record_1
CROSS JOIN (
 SELECT 1 AS n UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 10
) AS record_2
CROSS JOIN (SELECT @row_number := 0) AS init_user_param
SELECT  
 SUBSTRING_INDEX(
   SUBSTRING_INDEX(
      '1,2,3,4,50,51,52,53,54,55,56,100'
     ,',', 1
   )
   , ','
   , -1
 ) AS number
SELECT 
 number_list.number
FROM ( 

  SELECT
   DISTINCT 
   SUBSTRING_INDEX(
     SUBSTRING_INDEX(
        '1,2,3,4,50,51,52,53,54,55,56,100' #this is the number list
       ,',', number_generator.row_number
     )
     , ','
     , -1
 ) AS number
  FROM ( 
    SELECT 
     (@row_number := @row_number + 1) AS row_number
    FROM (
     SELECT 1 AS n UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 10
    ) AS record_1
    CROSS JOIN (
     SELECT 1 AS n UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 10
    ) AS record_2
    CROSS JOIN (SELECT @row_number := 0) AS init_user_param
  ) AS number_generator 
) AS number_list
LEFT JOIN 
 Table1
ON
 number_list.number = Table1.tab_id
WHERE
  Table1.tab_id IS NULL
drop table if exists tableA ;
create table tableA (tabId int) ;
insert into tableA (tabId) values
    (1), (2), (3), (4), (22), (19), (50), (51), (52), (53), (54), (55), (56), (88), (76), (100) ;


drop table if exists tableB ;
create table tableB (tabId int) ;
insert into tableB (tabId) values
    (1), (5), (3), (4), (22), (19), (50), (56), (88), (76), (100) ;

select *
    from tableA
    where tableA.tabId not in (select tabId from tableB) ;

2
51
52
53
54
55
-- ----------------------------------------------------------------
-- Example 2: Which Id's are in which table
--
select *
    from
    (
        select distinct tabId from tableA
        union
        select distinct tabId from tableB
    ) as unionAB
    left join tableA on unionAB.tabId = tableA.tabId
    left join tableB on unionAB.tabId = tableB.tabId
    order by unionAB.tabId
;

/*
tabId |tabId |tabId |
------|------|------|
     1|     1|     1|
     2|     2|[NULL]|
     3|     3|     3|
     4|     4|     4|
     5|[NULL]|     5|
    19|    19|    19|
    22|    22|    22|
    50|    50|    50|
    51|    51|[NULL]|
    52|    52|[NULL]|
    53|    53|[NULL]|
    54|    54|[NULL]|
    55|    55|[NULL]|
    56|    56|    56|
    76|    76|    76|
    88|    88|    88|
   100|   100|   100|
*/


-- ----------------------------------------------------------------
-- Example 3: Which Id's are missing from both tables
--
-- Determine the start/end of the range of Id's
set @startId = least((select min(tabId) from tableA), (select min(tabId) from tableB)) ;
set @endId = greatest((select max(tabId) from tableA), (select max(tabId) from tableB)) ;
select @startId, @endId ;

/*
@startId|@endId|
--------|------|
       1|   100|
*/

-- Build the full list of Id's from min to max (no gaps), using a "Common Table Expression"
-- This is based on @Brad's post in Stackoverflow: https://stackoverflow.com/questions/2157282/generate-days-from-date-range
with recursive lstIds as 
(
    select @startId as 'tabId'
    union
    select lstIds.tabId + 1 as 'tabId' 
        from lstIds
        where lstIds.tabId < @endId
)   -- no trailing ';' needed/allowed
-- Extract the new data so that it can be used
    -- Note: this 'select' needs to be imediately after the 'with' block
select *
    from lstIds
    -- Join the other tables into the full list
    left join tableA on lstIds.tabId = tableA.tabId
    left join tableB on lstIds.tabId = tableB.tabId
    -- where isnull(tableA.tabId) and isnull(tableB.tabId)  -- uncomment this line to see only the Id's that don't have a match in both tables
    order by lstIds.tabId
;


/*
tabId |tabId |tabId |
------|------|------|
     1|     1|     1|
     2|     2|[NULL]|
     3|     3|     3|
     4|     4|     4|
     5|[NULL]|     5|
     6|[NULL]|[NULL]|
     7|[NULL]|[NULL]|
            { snipped repeated nulls }
    17|[NULL]|[NULL]|
    18|[NULL]|[NULL]|
    19|    19|    19|
    20|[NULL]|[NULL]|
    21|[NULL]|[NULL]|
    22|    22|    22|
    23|[NULL]|[NULL]|
    24|[NULL]|[NULL]|
            { snipped repeated nulls }
    48|[NULL]|[NULL]|
    49|[NULL]|[NULL]|
    50|    50|    50|
    51|    51|[NULL]|
    52|    52|[NULL]|
    53|    53|[NULL]|
    54|    54|[NULL]|
    55|    55|[NULL]|
    56|    56|    56|
    57|[NULL]|[NULL]|
    58|[NULL]|[NULL]|
            { snipped repeated nulls }
    74|[NULL]|[NULL]|
    75|[NULL]|[NULL]|
    76|    76|    76|
    77|[NULL]|[NULL]|
    78|[NULL]|[NULL]|
            { snipped repeated nulls }
    86|[NULL]|[NULL]|
    87|[NULL]|[NULL]|
    88|    88|    88|
    89|[NULL]|[NULL]|
    90|[NULL]|[NULL]|
            { snipped repeated nulls }
    98|[NULL]|[NULL]|
    99|[NULL]|[NULL]|
   100|   100|   100|
*/