2009-07-29 43 views
41

Tôi muốn tìm hiểu cách kết hợp hai bảng db không có trường chung. Tôi đã kiểm tra UNION nhưng MSDN nói:Kết hợp hai bảng không có các trường chung

Sau đây là những nguyên tắc cơ bản để kết hợp các bộ kết quả của hai truy vấn bằng cách sử dụng UNION:

  1. Số lượng và thứ tự của các cột phải giống nhau trong tất cả các truy vấn.
  2. Các loại dữ liệu phải tương thích.

Nhưng tôi hoàn toàn không có điểm chung nào cả. Tất cả những gì tôi muốn là kết hợp chúng trong một cái bàn như một cái nhìn.

Vì vậy, tôi nên làm gì?

Xin cảm ơn trước.

Trân trọng.

+1

cho những người không thể nghĩ ra một cách sử dụng thực tế hợp lý, hãy tưởng tượng điều này: bạn có một bảng phiếu quà tặng. bạn đang thực hiện một số chỉnh sửa thủ công trên db và bạn muốn đặt trước (đặt ID thành viên cho) N của phiếu thưởng cho N người có trong kết quả truy vấn của bạn. Bạn có thể sử dụng con trỏ, hoặc một ứng dụng được viết bằng ngôn ngữ khác, nhưng một sql sạch với một CTE chỉ phù hợp với các hóa đơn, mà không có bạn rời khỏi phiên SQL của bạn. -và số hàng là cách để đi – SuperDuck

+0

Đây là câu hỏi MySql fav của tôi! – FisherCoder

Trả lời

92

Có một số cách để thực hiện việc này, tùy thuộc vào những gì bạn thực sự là muốn. Không có cột phổ biến, bạn cần quyết định xem bạn có muốn giới thiệu một cột chung hay lấy sản phẩm hay không.

Hãy nói rằng bạn có hai bảng:

parts:    custs: 
+----+----------+ +-----+------+ 
| id | desc  | | id | name | 
+----+----------+ +-----+------+ 
| 1 | Sprocket | | 100 | Bob | 
| 2 | Flange | | 101 | Paul | 
+----+----------+ +-----+------+ 

Quên các cột thực tế kể từ khi bạn muốn có khả năng nhất một khách hàng/đặt hàng/mối quan hệ là một phần trong trường hợp này; Tôi vừa mới sử dụng các cột đó để minh họa các cách để làm điều đó.

Một sản phẩm Descartes sẽ phù hợp với tất cả các hàng trong bảng đầu tiên với tất cả các hàng trong thứ hai:

> select * from parts, custs; 
     id desc  id name 
     -- ----  --- ---- 
     1 Sprocket 101 Bob 
     1 Sprocket 102 Paul 
     2 Flange 101 Bob 
     2 Flange 102 Paul 

Đó có lẽ không phải những gì bạn muốn từ 1000 các bộ phận và 100 khách hàng sẽ cho kết quả 100.000 hàng với rất nhiều nhân đôi thông tin. Ngoài ra, bạn có thể sử dụng công đoàn để chỉ xuất dữ liệu, mặc dù không phải cạnh nhau (bạn sẽ cần phải đảm bảo các loại cột tương thích giữa hai lựa chọn, hoặc bằng cách làm cho các cột trong bảng tương thích hoặc cố định chúng trong chọn):

> select id as pid, desc, '' as cid, '' as name from parts 
    union 
    select '' as pid, '' as desc, id as cid, name from custs; 
    pid desc  cid name 
    --- ----  --- ---- 
       101 Bob 
       102 Paul 
    1 Sprocket 
    2 Flange 

trong một số cơ sở dữ liệu, bạn có thể sử dụng một rowid/cột rownum hoặc giả cột để phù hợp với hồ sơ side-by-side, chẳng hạn như:

id desc  id name 
-- ----  --- ---- 
1 Sprocket 101 Bob 
2 Flange 101 Bob 

mã sẽ là một cái gì đó như:

select a.id, a.desc, b.id, b.name 
from parts a, custs b 
where a.rownum = b.rownum; 

Nó vẫn như một sản phẩm Descartes nhưng các giới hạn quy định tại khoản where cách các hàng được kết hợp để tạo kết quả (vì vậy không phải là một sản phẩm Descartes ở tất cả, thực sự).

Tôi chưa thử nghiệm SQL vì đây là một trong những hạn chế của DBMS mà tôi chọn, và đúng như vậy, tôi không tin rằng nó cần thiết trong một lược đồ được suy nghĩ đúng đắn. Vì SQL không đảm bảo thứ tự mà nó tạo dữ liệu, kết hợp có thể thay đổi mỗi lần bạn thực hiện truy vấn trừ khi bạn có một mối quan hệ cụ thể hoặc mệnh đề order by.

Tôi nghĩ điều lý tưởng cần làm là thêm cột vào cả hai bảng chỉ định mối quan hệ là gì. Nếu không có mối quan hệ thực sự, thì có thể bạn không có kinh doanh trong việc cố gắng đặt chúng cạnh nhau với SQL.

Nếu bạn chỉ muốn chúng được hiển thị song song trong báo cáo hoặc trên trang web (hai ví dụ), công cụ phù hợp để làm điều đó là bất cứ điều gì tạo báo cáo hoặc trang web của bạn, cùng với hai độc lập SQL truy vấn để có được hai bảng không liên quan. Ví dụ, một lưới hai cột trong BIRT (hoặc Crystal hoặc Jasper), mỗi bảng có một bảng dữ liệu riêng biệt hoặc một bảng hai cột HTML (hoặc CSS), mỗi bảng có một bảng dữ liệu riêng biệt.

+0

Cảm ơn, đó là câu trả lời khá tốt đẹp và chỉ cho tôi cách tốt hơn để đạt được giải pháp. – Tarik

+0

đã giúp tôi quá, do đó upvoted !! :) – KillABug

+0

Có rownum hoặc rowid trong MySQL không? – CMCDragonkai

3

Nếu các bảng không có các trường chung thì không có cách nào để kết hợp dữ liệu trong bất kỳ chế độ xem có ý nghĩa nào. Bạn sẽ có nhiều khả năng kết thúc bằng một chế độ xem có chứa dữ liệu trùng lặp từ cả hai bảng.

8
SELECT * 
FROM table1, table2 

Điều này sẽ tham gia mọi hàng trong bảng 1 với bảng 2 (sản phẩm Descartes) trả về tất cả các cột.

+0

Nếu chúng là các bảng cơ sở dữ liệu khác nhau thì sao? Cảm ơn. – Tarik

+4

Điều này sẽ gây ra một sự tham gia chéo, mà dường như không phải là những gì anh ta đang tìm kiếm. – SqlRyan

+0

Giải pháp thông minh! –

2

Để có được cái nhìn có ý nghĩa/hữu ích của hai bảng, bạn thường cần xác định trường nhận dạng từ mỗi bảng có thể được sử dụng trong mệnh đề ON trong JOIN.

sau đó theo quan điểm của bạn:

SELECT T1.*, T2.* FROM T1 JOIN T2 ON T1.IDFIELD1 = T2.IDFIELD2 

Bạn đề cập đến không có trường là "chung", nhưng mặc dù các lĩnh vực xác định có thể không có cùng tên hoặc thậm chí là kiểu dữ liệu tương tự, bạn có thể sử dụng các chuyển đổi/chức năng đúc để tham gia cùng họ theo một cách nào đó.

+0

Ngay cả khi không có bất kỳ trường được chia sẻ trực tiếp nào, thì phải có một số mối quan hệ giữa các bảng để chế độ xem có ý nghĩa. Mối quan hệ đó cần phải được ghi lại trong mệnh đề ON. –

20

Đây là một yêu cầu rất lạ, và gần như chắc chắn bạn không bao giờ muốn làm gì trong một ứng dụng thực tế, nhưng từ quan điểm học thuật thuần túy, đó là một thử thách thú vị. Với SQL Server 2005 bạn có thể sử dụng các biểu bảng thông thường và các row_number() chức năng và tham gia vào đó:

with OrderedFoos as (
    select row_number() over (order by FooName) RowNum, * 
    from Foos (nolock) 
), 
OrderedBars as (
    select row_number() over (order by BarName) RowNum, * 
    from Bars (nolock) 
) 
select * 
from OrderedFoos f 
    full outer join OrderedBars u on u.RowNum = f.RowNum 

này hoạt động, nhưng nó vô cùng ngớ ngẩn và tôi cung cấp nó chỉ như là một "cộng đồng wiki" câu trả lời vì tôi thực sự sẽ không giới thiệu nó.

+1

+1 yeah số hàng là con đường để đi, nhưng tôi muốn sử dụng tham gia bên trong. để sử dụng thế giới thực, vui lòng xem nhận xét của tôi về câu hỏi -) – SuperDuck

+0

Đây là những gì tôi cần! Tôi đã được giao nhiệm vụ thực hiện một ràng buộc FK giữa hai bảng mà chỉ có trường chung là id trên một mối quan hệ một-nhiều ví dụ. TblA có 5 TblB và 5 TblC nhưng những thay đổi logic kinh doanh có nghĩa là mọi TblC bây giờ cần mối quan hệ 1-1 với TblB. Tôi phải hồi sinh lại mối quan hệ này để trường có thể được tạo ra độc đáo và không có khả năng di chuyển về phía trước. Điều này cung cấp một cách cho tôi để cư đó cho dữ liệu lịch sử đã có trong hệ thống – Kirlac

2

tại sao bạn không sử dụng phương pháp đơn giản

SELECT distinct * 
    FROM 
    SUPPLIER full join 
    CUSTOMER on (
     CUSTOMER.OID = SUPPLIER.OID 
    ) 

Nó cung cấp cho bạn tất cả các cột từ hai bảng và trả về tất cả hồ sơ từ khách hàng và nhà cung cấp nếu khách hàng có 3 hồ sơ và cung cấp đã 2 sau đó supplier'll hiển thị NULL trong tất cả các cột

1
select 
    status_id, 
    status, 
    null as path, 
    null as Description 
from 
    zmw_t_status 

union 
select 
    null, 
    null, 
    path as cid, 
    Description from zmw_t_path; 
+0

nó sẽ bỏ qua một trong những tên trường, tôi nghĩ bạn chỉ cần đặt bí danh tên trường trên công đoàn cuối – Ruskin

0
select * from this_table; 

select distinct person from this_table 

union select address as location from that_table 

drop wrong_table from this_database; 
-1

Vui lòng thử truy vấn này:

Kết hợp hai bảng mà không có cột điểm chung:

SELECT * 
FROM table1 

UNION 

SELECT * 
FROM table2 
ORDER BY orderby ASC 
+0

Điều này chỉ hoạt động khi cả hai bảng có số biểu thức bằng nhau – MacSalty

1
SELECT t1.col table1col, t2.col table2col 
FROM table1 t1 
JOIN table2 t2 on t1.table1Id = x and t2.table2Id = y 
+0

Trong khi mã này có thể trả lời câu hỏi, cung cấp ngữ cảnh bổ sung liên quan đến _why_ và/hoặc _how_ nó trả lời câu hỏi sẽ cải thiện đáng kể giá trị dài hạn của nó. Xin vui lòng [sửa] câu trả lời của bạn để thêm một số lời giải thích. –

2
Select 
DISTINCT t1.col,t2col 
From table1 t1, table2 t2 

OR 

Select 
DISTINCT t1.col,t2col 
From table1 t1 
cross JOIN table2 t2 

nếu dữ liệu ôm nó, nó mất thời gian dài ..

1

thử:

select * from table 1 left join table2 as t on 1 = 1; 

này sẽ mang lại tất cả các cột từ cả hai bàn.

+1

Cảm ơn bạn đã trích đoạn mã này, đoạn mã này có thể cung cấp một số trợ giúp ngay lập tức. Một lời giải thích thích hợp [sẽ cải thiện rất nhiều] (// meta.stackexchange.com/q/114762) giá trị giáo dục của nó bằng cách hiển thị * tại sao * đây là một giải pháp tốt cho vấn đề, và sẽ hữu ích hơn cho các độc giả tương lai tương tự, nhưng không giống nhau, câu hỏi. Vui lòng [sửa] câu trả lời của bạn để thêm giải thích và đưa ra chỉ dẫn về những giới hạn và giả định được áp dụng. –

Các vấn đề liên quan