67

我想学习如何组合两个没有共同字段的数据库表。我检查了 UNION 但 MSDN 说:

以下是使用 UNION 组合两个查询的结果集的基本规则:

  1. 在所有查询中,列的数量和顺序必须相同。
  2. 数据类型必须兼容。

但我根本没有共同的领域。我想要的只是像视图一样将它们组合在一个表中。

所以我该怎么做?

4

14 回答 14

131

有很多方法可以做到这一点,这取决于你真正想要什么。没有公共栏目,你需要决定是要引入公共栏目还是要产品。

假设您有两个表:

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

忘记实际的列,因为在这种情况下您很可能客户/订单/零件关系;我刚刚使用这些列来说明如何做到这一点。

笛卡尔积将第一个表中的每一行与第二个表中的每一行匹配:

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

这可能不是您想要的,因为 1000 个零件和 100 个客户会导致 100,000 行包含大量重复信息。

或者,您可以使用联合来仅输出数据,尽管不是并排(您需要确保列类型在两个选择之间兼容,方法是使表列兼容或在选择中强制它们):

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

在某些数据库中,您可以使用 rowid/rownum 列或伪列来并排匹配记录,例如:

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

代码将类似于:

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

它仍然一个笛卡尔积,但该where子句限制了如何组合行以形成结果(所以根本不是笛卡尔积,真的)。

我没有为此测试该 SQL,因为它是我选择的 DBMS 的限制之一,因此,我认为在经过适当考虑的模式中不需要它。由于 SQL 不保证它生成数据的顺序,因此每次执行查询时匹配都会发生变化,除非您有特定的关系或order by子句。

我认为理想的做法是在两个表中添加一列,指定关系是什么。如果没有真正的关系,那么您可能没有必要尝试将它们与 SQL 并排放置。

如果您只是希望它们在报告或网页上并排显示(两个示例),那么执行此操作的正确工具是生成您的报告或网页,再加上两个独立的 SQL 查询以获得两个不相关的表。例如,BIRT(或 Crystal 或 Jasper)中的两列网格每个都有一个单独的数据表,或者一个 HTML 两列表(或 CSS)每个都有一个单独的数据表。

于 2009-07-29T05:48:09.073 回答
26

这是一个非常奇怪的要求,几乎可以肯定,这是您在现实世界的应用程序中永远不想做的事情,但从纯粹的学术角度来看,这是一个有趣的挑战。使用 SQL Server 2005,您可以使用公用表表达式和 row_number() 函数并加入:

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

这可行,但它非常愚蠢,我仅将其作为“社区 wiki”答案提供,因为我真的不推荐它。

于 2009-07-29T05:11:52.923 回答
11
SELECT *
FROM table1, table2

这会将 table1 中的每一行与返回所有列的 table2 (笛卡尔积)连接起来。

于 2009-07-29T05:04:38.897 回答
5
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;
于 2014-05-22T09:54:02.920 回答
5

尝试:

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

这将带来两个表中的所有列。

于 2017-09-01T10:45:52.297 回答
3

如果表没有公共字段,则无法在任何有意义的视图中组合数据。您更有可能最终得到一个包含两个表中重复数据的视图。

于 2009-07-29T05:03:15.670 回答
2

要获得两个表的有意义/有用的视图,您通常需要从每个表中确定一个标识字段,然后可以在 JOIN 的 ON 子句中使用该字段。

那么在你看来:

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

您提到没有字段是“通用的”,但是尽管识别字段可能没有相同的名称甚至是相同的数据类型,但您可以使用 convert / cast 函数以某种方式加入它们。

于 2009-07-29T05:10:31.647 回答
2

你为什么不使用简单的方法

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

它为您提供两个表中的所有列,如果客户有 3 条记录而供应商有 2 条记录,则返回客户和供应商的所有记录,然后供应商将在所有列中显示 NULL

于 2012-10-02T23:28:03.817 回答
2
Select 
DISTINCT  t1.col,t2col
From table1 t1, table2 t2

OR

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

如果它的拥抱数据,它需要很长时间..

于 2016-09-01T08:18:57.127 回答
1
SELECT t1.col table1col, t2.col table2col
FROM table1 t1 
JOIN table2 t2 on t1.table1Id = x and t2.table2Id = y
于 2016-04-01T14:13:23.100 回答
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;
于 2014-12-02T02:09:18.847 回答
0

当您必须使用三个选择语句执行此操作时非常困难

我尝试了所有建议的技术,但都是徒劳的

请看下面的脚本。如果您有其他解决方案,请告知

   select distinct x.best_Achiver_ever,y.Today_best_Achiver ,z.Most_Violator from 

    (SELECT  Top(4) ROW_NUMBER() over (order by tl.username)  AS conj, tl. 
     [username] + '-->' + str(count(*)) as best_Achiver_ever 
    FROM[TiketFollowup].[dbo].N_FCR_Tikect_Log_Archive tl
     group by tl.username
     order by count(*) desc) x
      left outer join 

(SELECT 
Top(4) ROW_NUMBER() over (order by tl.username)  as conj, tl.[username] + '-->' + str(count(*)) as Today_best_Achiver
FROM[TiketFollowup].[dbo].[N_FCR_Tikect_Log] tl
where convert(date, tl.stamp, 121) = convert(date,GETDATE(),121)
group by tl.username
order by count(*) desc) y 
on x.conj=y.conj

 left outer join 

(
select  ROW_NUMBER() over (order by count(*)) as conj,username+ '--> ' + str( count(dbo.IsViolated(stamp))) as Most_Violator from N_FCR_Ticket
where dbo.IsViolated(stamp) = 'violated' and  convert(date,stamp, 121) < convert(date,GETDATE(),121)
group by username
order by count(*) desc) z
on x.conj = z.conj
于 2019-02-20T13:43:26.510 回答
0

连接不相关的表

在此处输入图像描述

演示 SQL 脚本

IF OBJECT_ID('Tempdb..#T1') IS NOT NULL  DROP TABLE #T1;

CREATE TABLE #T1 (T1_Name VARCHAR(75));

INSERT INTO #T1 (T1_Name) VALUES ('Animal'),('Bat'),('Cat'),('Duet');

SELECT * FROM #T1;

IF OBJECT_ID('Tempdb..#T2') IS NOT NULL  DROP TABLE #T2;

CREATE TABLE #T2 (T2_Class VARCHAR(10));

INSERT INTO #T2 (T2_Class) VALUES ('Z'),('T'),('H'); 

SELECT * FROM #T2;

为了加入非相关表,我们将介绍一个常见的序列号加入列,如下所示。

SQL 脚本

SELECT T1.T1_Name,ISNULL(T2.T2_Class,'') AS T2_Class FROM
( SELECT T1_Name,ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS S_NO FROM #T1) T1
LEFT JOIN
( SELECT T2_Class,ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS S_NO FROM #T2) T2
ON t1.S_NO=T2.S_NO;
于 2020-01-18T06:40:22.730 回答
-2

请尝试以下查询:

合并两个没有公共列的表:

SELECT * 
FROM table1 

UNION 

SELECT * 
FROM table2  
ORDER BY orderby ASC
于 2015-01-28T12:29:29.060 回答