การรวมตารางสองตารางที่มีจำนวนคอลัมน์ต่างกัน


107

ฉันมีสองตาราง (ตาราง A และตาราง B)

คอลัมน์เหล่านี้มีจำนวนคอลัมน์ที่แตกต่างกัน - สมมติว่าตาราง A มีคอลัมน์มากกว่า

ฉันจะรวมสองตารางนี้และรับค่าว่างสำหรับคอลัมน์ที่ตาราง B ไม่มีได้อย่างไร

คำตอบ:


217

เพิ่มคอลัมน์พิเศษเป็นค่าว่างสำหรับตารางที่มีคอลัมน์น้อยเช่น

Select Col1, Col2, Col3, Col4, Col5 from Table1
Union
Select Col1, Col2, Col3, Null as Col4, Null as Col5 from Table2

6
มีวิธีกรอกค่าเริ่มต้นสำหรับคอลัมน์ Null หรือไม่?
Hans

3
@Hans: คุณสามารถทำบางสิ่งเช่น isnull (ColumnName, 0) เป็น ColumnName หรือ isnull (ColumnName, '-') เป็น ColumnName หรือสิ่งที่คล้ายกัน
กังกัน

3
ฉันตระหนักว่าโซลูชันนี้ใช้งานได้โดยไม่ต้องแสดงรายการคอลัมน์ทั้งหมด ดังนั้นแทนที่จะหนึ่งยังสามารถทำได้Select Col1, Col2, Col3, Null as Col4, Null as Col5 from Table2 Select *, Null as Col4, Null as Col5 from Table2
Pratik Patel

สำหรับค่า null แฮ็คนี้ใช้ได้กับฉัน: 'SomeString' เป็น DummyColumn โดยทั่วไปคุณเพียงแค่แทนที่ค่า NULL ด้วยค่าบางค่า สิ่งนี้ยังใช้ได้เมื่อใช้กับ groupby
Saurabh Jain

8

ฉันมาที่นี่และทำตามคำตอบด้านบน แต่ลำดับประเภทข้อมูลไม่ตรงกันทำให้เกิดข้อผิดพลาด คำอธิบายด้านล่างจากคำตอบอื่นจะเป็นประโยชน์

ผลลัพธ์ด้านบนเหมือนกับลำดับของคอลัมน์ในตารางของคุณหรือไม่ เนื่องจาก oracle เข้มงวดในคำสั่งคอลัมน์ ตัวอย่างด้านล่างนี้ก่อให้เกิดข้อผิดพลาด:

create table test1_1790 (
col_a varchar2(30),
col_b number,
col_c date);

create table test2_1790 (
col_a varchar2(30),
col_c date,
col_b number);

select * from test1_1790
union all
select * from test2_1790;

ORA-01790: นิพจน์ต้องมีประเภทข้อมูลเดียวกันกับนิพจน์ที่เกี่ยวข้อง

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

เลือก col_a, col_b, col_c จาก test1_1790 union ทั้งหมดเลือก col_a, col_b, col_c จาก test2_1790; สถานการณ์ที่พบบ่อยขึ้นสำหรับข้อผิดพลาดนี้คือเมื่อคุณสลับ (หรือเปลี่ยน) คอลัมน์สองคอลัมน์ขึ้นไปโดยไม่ได้ตั้งใจในรายการ SELECT:

select col_a, col_b, col_c from test1_1790
union all
select col_a, col_c, col_b from test2_1790;

หรือหากข้างต้นไม่สามารถแก้ปัญหาของคุณได้วิธีการสร้าง ALIASในคอลัมน์เช่นนี้: (แบบสอบถามไม่เหมือนกับของคุณ แต่ประเด็นคือวิธีการเพิ่มนามแฝงในคอลัมน์)

SELECT id_table_a, 
       desc_table_a, 
       table_b.id_user as iUserID, 
       table_c.field as iField
UNION
SELECT id_table_a, 
       desc_table_a, 
       table_c.id_user as iUserID, 
       table_c.field as iField

ฉันต้องใช้สิ่งเดียวกัน แต่ฉันเพิ่ม a.col_name และ b.col_name สำหรับคอลัมน์ที่ไม่ใช่ null สำหรับคอลัมน์ null ฉันต้องใช้: NULL AS col_name1, NULL AS col_name2 ฯลฯ
Scott R

1
หมายเหตุ SELECT * UNION สามารถถูกล่ามโซ่ได้หลายครั้ง หมายเหตุตัวกรอง WHERE สามารถใช้ได้ในทุกประโยค SELECT
mirekphd

1

โดยปกติคุณต้องมีจำนวนคอลัมน์เท่ากันเมื่อคุณใช้ตัวดำเนินการตามชุดคำตอบของ Kangkanจึงถูกต้อง

SAS SQL มีตัวดำเนินการเฉพาะเพื่อจัดการสถานการณ์นั้น:

SAS (R) 9.3 คู่มือผู้ใช้โพรซีเดอร์ SQL

คีย์เวิร์ด CORRESPONDING (CORR)

คีย์เวิร์ด CORRESPONDING จะใช้เมื่อระบุตัวดำเนินการ set เท่านั้น CORR ทำให้ PROC SQL จับคู่คอลัมน์ในนิพจน์ตารางตามชื่อไม่ใช่ตามตำแหน่งลำดับ คอลัมน์ที่ไม่ตรงตามชื่อจะไม่รวมอยู่ในตารางผลลัพธ์ยกเว้นตัวดำเนินการ OUTER UNION

SELECT * FROM tabA
OUTER UNION CORR
SELECT * FROM tabB;

สำหรับ:

+---+---+
| a | b |
+---+---+
| 1 | X |
| 2 | Y |
+---+---+

OUTER UNION CORR

+---+---+
| b | d |
+---+---+
| U | 1 |
+---+---+

<=>

+----+----+---+
| a  | b  | d |
+----+----+---+
|  1 | X  |   |
|  2 | Y  |   |
|    | U  | 1 |
+----+----+---+

U-SQL สนับสนุนแนวคิดที่คล้ายกัน:

นอกสหภาพตามชื่อบน (*)

ภายนอก

ต้องการอนุประโยค BY NAME และรายการ ON ซึ่งตรงข้ามกับนิพจน์ชุดอื่น ๆ สคีมาเอาต์พุตของ OUTER UNION มีทั้งคอลัมน์ที่ตรงกันและคอลัมน์ที่ไม่ตรงกันจากทั้งสองด้าน สิ่งนี้จะสร้างสถานการณ์ที่แต่ละแถวที่มาจากด้านใดด้านหนึ่งมี "คอลัมน์ที่ขาดหายไป" ซึ่งอยู่ในอีกด้านหนึ่งเท่านั้น สำหรับคอลัมน์ดังกล่าวจะมีการระบุค่าเริ่มต้นสำหรับ "เซลล์ที่หายไป" ค่าดีฟอลต์คือ null สำหรับชนิด nullable และค่าดีฟอลต์. Net สำหรับชนิดที่ไม่เป็นโมฆะ (เช่น 0 สำหรับ int)

โดยชื่อ

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

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

และรหัส:

@result =    
    SELECT * FROM @left
    OUTER UNION BY NAME ON (*) 
    SELECT * FROM @right;

แก้ไข:

KQLสนับสนุนแนวคิดของสหภาพภายนอก:

ชนิด:

inner - ผลลัพธ์มีส่วนย่อยของคอลัมน์ที่ใช้ร่วมกันกับตารางอินพุตทั้งหมด

ด้านนอก - ผลลัพธ์มีคอลัมน์ทั้งหมดที่เกิดขึ้นในอินพุตใด ๆ เซลล์ที่ไม่ได้กำหนดโดยแถวอินพุตจะถูกตั้งค่าเป็น null

ตัวอย่าง:

let t1 = datatable(col1:long, col2:string)  
[1, "a",  
2, "b",
3, "c"];
let t2 = datatable(col3:long)
[1,3];
t1 | union kind=outer t2;

เอาท์พุต:

+------+------+------+
| col1 | col2 | col3 |
+------+------+------+
|    1 | a    |      |
|    2 | b    |      |
|    3 | c    |      |
|      |      |    1 |
|      |      |    3 |
+------+------+------+

การสาธิต


มีความคิดอย่างไรที่จะบรรลุสิ่งนี้ใน SQL ??
KetanVaghasiya

@KetanVaghasiya เท่าที่ฉันรู้มีเพียง SAS SQL และ U-SQL เท่านั้นที่สนับสนุนแนวคิดนี้
Lukasz Szozda

0

สำหรับคอลัมน์พิเศษใด ๆ หากไม่มีการแมปให้แมปเป็น null เช่นแบบสอบถาม SQL ต่อไปนี้

Select Col1, Col2, Col3, Col4, Col5 from Table1
Union
Select Col1, Col2, Col3, Null as Col4, Null as Col5 from Table2````

-1

หากมีเพียง 1 แถวคุณสามารถใช้ join ได้

Select t1.Col1, t1.Col2, t1.Col3, t2.Col4, t2.Col5 from Table1 t1 join Table2 t2;

การรวมกันของตาราง 1 แถวสองชุด (ความสัมพันธ์แบบหลายชุดแต่ละชุดกับทูเพิลหนึ่งตัว) จะมีสองแถว (ทูเปิล) ในความสัมพันธ์ที่เป็นผลลัพธ์ ในพีชคณิตเชิงสัมพันธ์ (ซึ่ง SQL ไม่ใช่) ผลลัพธ์การรวมอาจเป็นหนึ่งแถวแม้ว่าความสัมพันธ์ของอินพุตทั้งสองจะมีทูเพิลที่เหมือนกันเช่น การรวมตัวกันของความสัมพันธ์แบบทูเพิล
Robert Monfera
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.