จะหาช่องว่างในลำดับเลขใน mysql ได้อย่างไร?


120

เรามีฐานข้อมูลพร้อมตารางที่มีการนำเข้าค่าจากระบบอื่น มีคอลัมน์เพิ่มอัตโนมัติและไม่มีค่าที่ซ้ำกัน แต่มีค่าที่หายไป ตัวอย่างเช่นการเรียกใช้แบบสอบถามนี้:

select count(id) from arrc_vouchers where id between 1 and 100

ควรคืนค่า 100 แต่ส่งกลับ 87 แทน มีคำถามใดบ้างที่ฉันสามารถเรียกใช้ที่จะคืนค่าของตัวเลขที่หายไป ตัวอย่างเช่นอาจมีระเบียนสำหรับ id 1-70 และ 83-100 แต่ไม่มีระเบียนใดที่มี id เป็น 71-82 ฉันต้องการส่งคืน 71, 72, 73 ฯลฯ

เป็นไปได้หรือไม่


สิ่งนี้อาจใช้ไม่ได้ใน MySQL แต่ในที่ทำงาน (Oracle) เราต้องการสิ่งที่คล้ายกัน เราเขียน Stored Proc ที่ใช้ตัวเลขเป็นค่าสูงสุด จากนั้น Stored Proc จะสร้างตารางชั่วคราวที่มีคอลัมน์เดียว ตารางมีตัวเลขทั้งหมดตั้งแต่ 1 ถึงสูงสุด จากนั้นก็ไม่ได้เข้าร่วมระหว่างตารางชั่วคราวและตารางที่เราสนใจ ถ้าคุณเรียกมันด้วย Max = Select max (id) จาก arrc_vouchers มันจะส่งคืนค่าที่หายไปทั้งหมด
saunderl

2
เกิดอะไรขึ้นกับการมีช่องว่างในการกำหนดหมายเลข? ค่าของคีย์ตัวแทนโดยทั่วไปไม่มีความหมาย สิ่งที่สำคัญคือมันไม่เหมือนใคร หากแอปพลิเคชันของคุณไม่สามารถจัดการ ID ที่ไม่ติดกันได้นั่นอาจเป็นข้อบกพร่องในแอปพลิเคชันไม่ใช่ในข้อมูล
Wyzard

4
ในกรณีนี้เป็นปัญหาเนื่องจากข้อมูลที่เรารับมาจากระบบเก่าใช้หมายเลขเพิ่มอัตโนมัติที่เชื่อมโยงกับบันทึกเป็นกุญแจสำคัญในการพิมพ์บนการ์ดจริงที่ส่งให้กับผู้คน นี่ไม่ใช่ความคิดของเรา ในการค้นหาว่าการ์ดใดหายไปเราจำเป็นต้องทราบว่าช่องว่างอยู่ที่ใดในการเรียงลำดับเลข
EmmyS

xaprb.com/blog/2005/12/06/… select l.id + 1 as start from sequence as l left outer join sequence as r on l.id + 1 = r.id where r.id is null;

คุณสามารถใช้สร้างซีรีส์เพื่อสร้างตัวเลขตั้งแต่ 1 ถึง ID สูงสุดของตารางของคุณ จากนั้นเรียกใช้แบบสอบถามโดยที่ id ไม่อยู่ในชุดนี้
Tsvetelin Salutski

คำตอบ:


170

ปรับปรุง

ConfexianMJS ให้คำตอบที่ดีกว่ามาก ในแง่ของประสิทธิภาพ

คำตอบ (ไม่เร็วที่สุด)

นี่คือเวอร์ชันที่ใช้งานได้กับตารางทุกขนาด (ไม่ใช่แค่ 100 แถว):

SELECT (t1.id + 1) as gap_starts_at, 
       (SELECT MIN(t3.id) -1 FROM arrc_vouchers t3 WHERE t3.id > t1.id) as gap_ends_at
FROM arrc_vouchers t1
WHERE NOT EXISTS (SELECT t2.id FROM arrc_vouchers t2 WHERE t2.id = t1.id + 1)
HAVING gap_ends_at IS NOT NULL
  • gap_starts_at - รหัสแรกในช่องว่างปัจจุบัน
  • gap_ends_at - รหัสสุดท้ายในช่องว่างปัจจุบัน

6
ฉันไม่ได้ทำงานให้กับ บริษัท นั้นอีกต่อไป แต่นี่เป็นคำตอบที่ดีที่สุดที่ฉันเคยเห็นและมันก็คุ้มค่าที่จะจดจำไว้ใช้อ้างอิงในอนาคต ขอบคุณ!
EmmyS

4
ปัญหาเดียวของเรื่องนี้คือมันไม่ "รายงาน" ช่องว่างเริ่มต้นที่เป็นไปได้ เช่นถ้ารหัส 5 ตัวแรกหายไป (1 ถึง 5) ก็ไม่ได้แสดงว่า ... เราจะแสดงช่องว่างที่น่าสงสารได้อย่างไรในตอนเริ่มต้น?
DiegoDD

หมายเหตุ: แบบสอบถามนี้ใช้ไม่ได้กับตารางชั่วคราว ปัญหาของฉันคือorder numberฉันค้นหาช่องว่างไม่แตกต่างกัน (ตารางเก็บรายการคำสั่งซื้อดังนั้นหมายเลขคำสั่งซื้อที่เป็นของซ้ำสำหรับแต่ละบรรทัด) แบบสอบถามที่ 1: 2,812 แถวในชุด (1 นาที 31.09 วินาที) สร้างตารางอื่นโดยเลือกหมายเลขคำสั่งซื้อที่แตกต่างกัน คำถามของคุณโดยไม่มีการทำซ้ำของฉัน: 1009 แถวในชุด (18.04 วินาที)
Chris K

1
@DiegoDD เกิดอะไรขึ้นSELECT MIN(id) FROM table?
อากาศ

8
ทำงาน แต่ใช้เวลาประมาณ 5 ชั่วโมงในการทำงานบนโต๊ะที่มีบันทึก 700000 รายการ
Matt

98

สิ่งนี้ได้ผลสำหรับฉันในการหาช่องว่างในตารางที่มีแถวมากกว่า 80k:

SELECT
 CONCAT(z.expected, IF(z.got-1>z.expected, CONCAT(' thru ',z.got-1), '')) AS missing
FROM (
 SELECT
  @rownum:=@rownum+1 AS expected,
  IF(@rownum=YourCol, 0, @rownum:=YourCol) AS got
 FROM
  (SELECT @rownum:=0) AS a
  JOIN YourTable
  ORDER BY YourCol
 ) AS z
WHERE z.got!=0;

ผลลัพธ์:

+------------------+
| missing          |
+------------------+
| 1 thru 99        |
| 666 thru 667     |
| 50000            |
| 66419 thru 66456 |
+------------------+
4 rows in set (0.06 sec)

โปรดทราบว่าลำดับของคอลัมน์expectedและgotมีความสำคัญ

หากคุณรู้YourColว่าไม่ได้เริ่มต้นที่ 1 และไม่สำคัญคุณสามารถแทนที่ได้

(SELECT @rownum:=0) AS a

กับ

(SELECT @rownum:=(SELECT MIN(YourCol)-1 FROM YourTable)) AS a

ผลลัพธ์ใหม่:

+------------------+
| missing          |
+------------------+
| 666 thru 667     |
| 50000            |
| 66419 thru 66456 |
+------------------+
3 rows in set (0.06 sec)

หากคุณต้องการดำเนินงานเชลล์สคริปต์บางอย่างบน ID ที่หายไปคุณยังสามารถใช้ตัวแปรนี้เพื่อสร้างนิพจน์โดยตรงที่คุณสามารถทำซ้ำใน bash ได้

SELECT GROUP_CONCAT(IF(z.got-1>z.expected, CONCAT('$(',z.expected,' ',z.got-1,')'), z.expected) SEPARATOR " ") AS missing
FROM (  SELECT   @rownum:=@rownum+1 AS expected,   IF(@rownum=height, 0, @rownum:=height) AS got  FROM   (SELECT @rownum:=0) AS a   JOIN block   ORDER BY height  ) AS z WHERE z.got!=0;

สิ่งนี้ก่อให้เกิดผลลัพธ์เช่นนั้น

$(seq 1 99) $(seq 666 667) 50000 $(seq 66419 66456)

จากนั้นคุณสามารถคัดลอกและวางลงใน for loop ใน bash terminal เพื่อดำเนินการคำสั่งสำหรับทุก ID

for ID in $(seq 1 99) $(seq 666 667) 50000 $(seq 66419 66456); do
  echo $ID
  # fill the gaps
done

มันเหมือนกับข้างบนเพียงแต่ว่ามันอ่านได้และปฏิบัติการได้ การเปลี่ยนคำสั่ง "CONCAT" ด้านบนจะทำให้สามารถสร้างไวยากรณ์สำหรับภาษาโปรแกรมอื่น ๆ ได้ หรือแม้แต่ SQL


8
ทางออกที่ดีสำหรับฉันมันดีกว่าคำตอบที่ต้องการ - ขอบคุณ
Wee Zel

6
มันมากมีประสิทธิภาพมากขึ้นกว่าคำตอบที่ได้รับการยอมรับ
symcbean

1
ไกลเร็วกว่าคำตอบที่ได้รับการยอมรับ สิ่งเดียวที่ฉันจะเพิ่มก็คือCONVERT( YourCol, UNSIGNED )จะให้ผลลัพธ์ที่ดีขึ้นหาก YourCol ยังไม่ได้เป็นจำนวนเต็ม
Barton Chittenden

1
@AlexandreCassagne: ถ้าฉันเข้าใจคำถามของคุณถูกต้องฉันจะทำแบบสอบถามแยกต่างหากเช่นเดียวกับคำถามที่ฝังไว้เพื่อค้นหาขั้นต่ำ:SELECT MAX(YourCol) FROM YourTable;
ConfexianMJS

1
@temuri เปลี่ยนเป็น GROUP_CONCAT หากจำเป็น:SELECT IF((z.got-IF(z.over>0, z.over, 0)-1)>z.expected, CONCAT(z.expected,' thru ',(z.got-IF(z.over>0, z.over, 0)-1)), z.expected) AS missing FROM ( SELECT @rownum:=@rownum+1 AS expected, @target-@missing AS under, (@missing:=@missing+IF(@rownum=YourCol, 0, YourCol-@rownum))-@target AS over, IF(@rownum=YourCol, 0, @rownum:=YourCol) AS got FROM (SELECT @rownum:=0, @missing:=0, @target:=10) AS a JOIN YourTable ORDER BY YourCol ) AS z WHERE z.got!=0 AND z.under>0;
ConfexianMJS

11

แบบสอบถามด่วนและสกปรกที่ควรทำเคล็ดลับ:

SELECT a AS id, b AS next_id, (b - a) -1 AS missing_inbetween
FROM 
 (
SELECT a1.id AS a , MIN(a2.id) AS b 
FROM arrc_vouchers  AS a1
LEFT JOIN arrc_vouchers AS a2 ON a2.id > a1.id
WHERE a1.id <= 100
GROUP BY a1.id
) AS tab

WHERE 
b > a + 1

สิ่งนี้จะให้ตารางแสดงรหัสที่มีรหัสที่หายไปด้านบนและ next_id ที่มีอยู่และจำนวนที่หายไประหว่าง ... เช่น

 
id next_id missing_in ระหว่าง
 1 4 2
68 70 1
75 87 11

1
สิ่งนี้ได้ผลดีสำหรับฉัน ขอบคุณ.! ฉันสามารถแก้ไขสิ่งนี้ตามวัตถุประสงค์ของฉันได้อย่างง่ายดาย
Rahim Khoja

ดูเหมือนว่านี่จะเป็นคำตอบที่ดีที่สุดเมื่อมองหา 'รหัสถัดไป' ในช่องว่าง น่าเสียดายที่มันช้ามากสำหรับตารางที่มีแถว 10K ฉันรอมากกว่า 10 นาทีบนโต๊ะ ~ 46K ในขณะที่ @ConfexianMJS ฉันได้ผลลัพธ์ในเวลาไม่ถึงวินาที!
BringBackC Commodore64

5

หากคุณกำลังใช้งานMariaDBคุณมีตัวเลือกที่เร็วกว่า (800%) โดยใช้เครื่องมือจัดเก็บข้อมูลลำดับ :

SELECT * FROM seq_1_to_50000 WHERE SEQ NOT IN (SELECT COL FROM TABLE);

2
เพื่อขยายความคิดนี้สามารถสร้างลำดับสูงสุดได้โดยใช้"SELECT MAX(column) FROM table"และตั้งค่าตัวแปรจากผลลัพธ์ที่บอกว่า $ MAX ... จากนั้นคำสั่ง sql สามารถเขียนได้"SELECT * FROM seq_1_to_". $MAX ." WHERE seq not in (SELECT column FROM table)" ไวยากรณ์ของฉันเป็น php
me_

หรือคุณสามารถใช้ SELECT @var:= max FROM ....; select * from .. WHERE seq < @max;กับตัวแปร MySQL
Moshe L

2

สร้างตารางชั่วคราวที่มี 100 แถวและคอลัมน์เดียวที่มีค่า 1-100

ภายนอกเข้าร่วมตารางนี้กับตาราง arrc_vouchers ของคุณและเลือกค่าคอลัมน์เดียวโดยที่รหัส arrc_vouchers เป็นโมฆะ

การเข้ารหัสนี้คนตาบอด แต่ควรใช้งานได้

select tempid from temptable 
left join arrc_vouchers on temptable.tempid = arrc_vouchers.id 
where arrc_vouchers.id is null

ตกลง 1 - 100 เป็นเพียงวิธีง่ายๆในการยกตัวอย่าง ในกรณีนี้เรากำลังดู 20,000 - 85,000 ฉันจะสร้างตารางชั่วคราวโดยมีแถว 65,000 แถว 20000 - 85000 หรือไม่ แล้วฉันจะไปทำอย่างนั้นได้อย่างไร? ฉันใช้ phpMyAdmin; ถ้าฉันตั้งค่าเริ่มต้นของคอลัมน์เป็น 25000 และเพิ่มขึ้นโดยอัตโนมัติฉันสามารถแทรก 65,000 แถวและมันจะเริ่มการเพิ่มอัตโนมัติด้วย 25000 ได้หรือไม่
EmmyS

ฉันมีสถานการณ์คล้าย ๆ กัน (ฉันมีสินค้า 100 รายการตามลำดับและต้องการค้นหารายการที่ขาดหายไป 100 ชิ้น) ในการทำเช่นนี้ฉันสร้างตาราง 1-100 ขึ้นมาใหม่จากนั้นเรียกใช้คำสั่งนี้กับมันและทำงานได้อย่างสวยงาม สิ่งนี้จะแทนที่ฟังก์ชันที่ซับซ้อนมากในการสร้างตารางชั่วคราว เพียงแค่คำแนะนำสำหรับคนที่อยู่ในสถานการณ์คล้าย ๆ กันบางครั้งการสร้างตารางก็เร็วกว่าตารางชั่วคราว
newshorts

2

ทางเลือกอื่นที่ต้องใช้แบบสอบถาม + โค้ดบางอย่างในการประมวลผลคือ:

select l.id lValue, c.id cValue, r.id rValue 
  from 
  arrc_vouchers l 
  right join arrc_vouchers c on l.id=IF(c.id > 0, c.id-1, null)
  left  join arrc_vouchers r on r.id=c.id+1
where 1=1
  and c.id > 0 
  and (l.id is null or r.id is null)
order by c.id asc;

โปรดทราบว่าแบบสอบถามไม่มีการเลือกย่อยใด ๆ ที่เรารู้ว่าไม่ได้รับการจัดการอย่างมีประสิทธิภาพโดยผู้วางแผนของ MySQL

ที่จะส่งคืนหนึ่งรายการต่อ centralValue (cValue) ที่ไม่มีค่าน้อยกว่า (lValue) หรือค่าที่มากกว่า (rValue) กล่าวคือ:

lValue |cValue|rValue
-------+------+-------
{null} | 2    | 3      
8      | 9    | {null} 
{null} | 22   | 23     
23     | 24   | {null} 
{null} | 29   | {null} 
{null} | 33   | {null} 


โดยไม่ต้องลงรายละเอียดเพิ่มเติม (เราจะเห็นในย่อหน้าถัดไป) ผลลัพธ์นี้หมายความว่า:

  • ไม่มีค่าระหว่าง 0 ถึง 2
  • ไม่มีค่าระหว่าง 9 ถึง 22
  • ไม่มีค่าระหว่าง 24 ถึง 29
  • ไม่มีค่าระหว่าง 29 ถึง 33
  • ไม่มีค่าระหว่าง 33 ถึง MAX VALUE

ดังนั้นแนวคิดพื้นฐานคือการทำ RIGHT และ LEFT ร่วมกับตารางเดียวกันโดยดูว่าเรามีค่า adjacents ต่อค่าหรือไม่ (กล่าวคือถ้าค่ากลางเป็น '3' เราจะตรวจสอบ 3-1 = 2 ทางซ้ายและ 3 + 1 ที่ ขวา) และเมื่อ ROW มีค่า NULL ที่ RIGHT หรือ LEFT เราจะรู้ว่าไม่มีค่าที่อยู่ติดกัน

ผลลัพธ์ดิบที่สมบูรณ์ของตารางของฉันคือ:

select * from arrc_vouchers order by id asc;

0  
2  
3  
4  
5  
6  
7  
8  
9  
22 
23 
24 
29 
33 

หมายเหตุบางประการ:

  1. จำเป็นต้องมีคำสั่ง SQL IF ในเงื่อนไขการรวมหากคุณกำหนดฟิลด์ 'id' เป็น UNSIGNED ดังนั้นจึงไม่อนุญาตให้คุณลดลงต่ำกว่าศูนย์ สิ่งนี้ไม่จำเป็นอย่างยิ่งหากคุณเก็บ c.value> 0 ไว้ตามที่ระบุไว้ในบันทึกถัดไป แต่ฉันจะรวมไว้ในรูปของ doc
  2. ฉันกำลังกรองค่าศูนย์ศูนย์เนื่องจากเราไม่สนใจค่าก่อนหน้าใด ๆ และเราสามารถรับค่าโพสต์จากแถวถัดไปได้

2

หากมีลำดับที่มีช่องว่างสูงสุดหนึ่งระหว่างตัวเลขสองตัว (เช่น 1,3,5,6) แบบสอบถามที่สามารถใช้ได้คือ:

select s.id+1 from source1 s where s.id+1 not in(select id from source1) and s.id+1<(select max(id) from source1);
  • table_name - source1
  • column_name - id

1

ตามคำตอบที่ให้ไว้ข้างต้นโดย Lucek ขั้นตอนการจัดเก็บนี้ช่วยให้คุณสามารถระบุชื่อตารางและคอลัมน์ที่คุณต้องการทดสอบเพื่อค้นหาระเบียนที่ไม่ติดกัน - ดังนั้นจึงตอบคำถามเดิมและสาธิตวิธีใช้ @var เพื่อแสดงตาราง & / หรือคอลัมน์ในกระบวนงานที่เก็บไว้

create definer=`root`@`localhost` procedure `spfindnoncontiguous`(in `param_tbl` varchar(64), in `param_col` varchar(64))
language sql
not deterministic
contains sql
sql security definer
comment ''
begin
declare strsql varchar(1000);
declare tbl varchar(64);
declare col varchar(64);

set @tbl=cast(param_tbl as char character set utf8);
set @col=cast(param_col as char character set utf8);

set @strsql=concat("select 
    ( t1.",@col," + 1 ) as starts_at, 
  ( select min(t3.",@col,") -1 from ",@tbl," t3 where t3.",@col," > t1.",@col," ) as ends_at
    from ",@tbl," t1
        where not exists ( select t2.",@col," from ",@tbl," t2 where t2.",@col," = t1.",@col," + 1 )
        having ends_at is not null");

prepare stmt from @strsql;
execute stmt;
deallocate prepare stmt;
end

1

ฉันลองใช้ด้วยวิธีที่แตกต่างกันและประสิทธิภาพที่ดีที่สุดที่ฉันพบคือคำถามง่ายๆนี้:

select a.id+1 gapIni
    ,(select x.id-1 from arrc_vouchers x where x.id>a.id+1 limit 1) gapEnd
    from arrc_vouchers a
    left join arrc_vouchers b on b.id=a.id+1
    where b.id is null
    order by 1
;

... เหลืออีกหนึ่งอันเพื่อตรวจสอบว่ามีIDถัดไปหรือไม่หากไม่พบถัดไปจากนั้นเคียวรีย่อยจะค้นหา id ถัดไปที่มีอยู่เพื่อค้นหาจุดสิ้นสุดของช่องว่าง ฉันทำเพราะแบบสอบถามที่มีเท่ากับ (=) มีประสิทธิภาพดีกว่าตัวดำเนินการมากกว่า (>)

การใช้sqlfiddleจะไม่แสดงประสิทธิภาพที่แตกต่างกันของแบบสอบถามอื่น ๆ แต่ในฐานข้อมูลจริงข้อความค้นหาข้างต้นนี้ให้ผลลัพธ์เร็วกว่าคำค้นหาอื่น 3 เท่า

สคีมา:

CREATE TABLE arrc_vouchers (id int primary key)
;
INSERT INTO `arrc_vouchers` (`id`) VALUES (1),(4),(5),(7),(8),(9),(10),(11),(15),(16),(17),(18),(19),(20),(21),(22),(23),(24),(25),(26),(27),(28),(29)
;

ทำตามคำค้นหาทั้งหมดที่ร้องเพื่อเปรียบเทียบประสิทธิภาพ:

select a.id+1 gapIni
    ,(select x.id-1 from arrc_vouchers x where x.id>a.id+1 limit 1) gapEnd
    from arrc_vouchers a
    left join arrc_vouchers b on b.id=a.id+1
    where b.id is null
    order by 1
;
select *, (gapEnd-gapIni) qt
    from (
        select id+1 gapIni
        ,(select x.id from arrc_vouchers x where x.id>a.id limit 1) gapEnd
        from arrc_vouchers a
        order by id
    ) a where gapEnd <> gapIni
;
select id+1 gapIni
    ,(select x.id from arrc_vouchers x where x.id>a.id limit 1) gapEnd
    #,coalesce((select id from arrc_vouchers x where x.id=a.id+1),(select x.id from arrc_vouchers x where x.id>a.id limit 1)) gapEnd
    from arrc_vouchers a
    where id+1 <> (select x.id from arrc_vouchers x where x.id>a.id limit 1)
    order by id
;
select id+1 gapIni
    ,coalesce((select id from arrc_vouchers x where x.id=a.id+1),(select x.id from arrc_vouchers x where x.id>a.id limit 1)) gapEnd
    from arrc_vouchers a
    order by id
;
select id+1 gapIni
    ,coalesce((select id from arrc_vouchers x where x.id=a.id+1),concat('*** GAT *** ',(select x.id from arrc_vouchers x where x.id>a.id limit 1))) gapEnd
    from arrc_vouchers a
    order by id
;

บางทีมันอาจช่วยใครบางคนและมีประโยชน์

คุณสามารถดูและทดสอบการสืบค้นของฉันโดยใช้sqlfiddleนี้:

http://sqlfiddle.com/#!9/6bdca7/1


0

แม้ว่าสิ่งเหล่านี้ดูเหมือนจะใช้ได้ผล แต่ชุดผลลัพธ์จะกลับมาในช่วงเวลาที่ยาวนานมากเมื่อมีข้อมูล 50,000 รายการ

ฉันใช้สิ่งนี้และพบช่องว่างหรือช่องว่างถัดไป (ใช้ล่าสุด + 1) พร้อมผลตอบแทนที่เร็วกว่ามากจากแบบสอบถาม

SELECT a.id as beforegap, a.id+1 as avail
FROM table_name a
where (select b.id from table_name b where b.id=a.id+1) is null
limit 1;

สิ่งนี้พบช่องว่างแรกซึ่งไม่ใช่สิ่งที่คำถามถาม
สิ้นสุด

0

อาจไม่เกี่ยวข้อง แต่ฉันกำลังมองหาสิ่งนี้เพื่อแสดงรายการช่องว่างตามลำดับตัวเลขและพบโพสต์นี้ซึ่งมีวิธีแก้ปัญหาที่แตกต่างกันหลายวิธีขึ้นอยู่กับสิ่งที่คุณกำลังมองหา ฉันกำลังมองหาช่องว่างแรกที่มีอยู่ในลำดับ (เช่นหมายเลขถัดไปที่ใช้ได้) และดูเหมือนว่าจะใช้ได้ดี

SELECT MIN (l.number_sequence + 1) เป็น nextavabile จากผู้ป่วยเป็นผู้ป่วย l LEFT OUTER JOIN เป็น r ใน l.number_sequence + 1 = r.number_sequence WHERE r.number_sequence เป็น NULL สถานการณ์และวิธีแก้ปัญหาอื่น ๆ อีกมากมายที่กล่าวถึงที่นั่นตั้งแต่ปี 2548!

วิธีค้นหาค่าที่ขาดหายไปในลำดับด้วย SQL

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.