我想学习如何组合两个没有共同字段的数据库表。我检查了 UNION 但 MSDN 说:
以下是使用 UNION 组合两个查询的结果集的基本规则:
- 在所有查询中,列的数量和顺序必须相同。
- 数据类型必须兼容。
但我根本没有共同的领域。我想要的只是像视图一样将它们组合在一个表中。
所以我该怎么做?
我想学习如何组合两个没有共同字段的数据库表。我检查了 UNION 但 MSDN 说:
以下是使用 UNION 组合两个查询的结果集的基本规则:
- 在所有查询中,列的数量和顺序必须相同。
- 数据类型必须兼容。
但我根本没有共同的领域。我想要的只是像视图一样将它们组合在一个表中。
所以我该怎么做?
有很多方法可以做到这一点,这取决于你真正想要什么。没有公共栏目,你需要决定是要引入公共栏目还是要产品。
假设您有两个表:
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)每个都有一个单独的数据表。
这是一个非常奇怪的要求,几乎可以肯定,这是您在现实世界的应用程序中永远不想做的事情,但从纯粹的学术角度来看,这是一个有趣的挑战。使用 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”答案提供,因为我真的不推荐它。
SELECT *
FROM table1, table2
这会将 table1 中的每一行与返回所有列的 table2 (笛卡尔积)连接起来。
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;
尝试:
select * from table 1 left join table2 as t on 1 = 1;
这将带来两个表中的所有列。
如果表没有公共字段,则无法在任何有意义的视图中组合数据。您更有可能最终得到一个包含两个表中重复数据的视图。
要获得两个表的有意义/有用的视图,您通常需要从每个表中确定一个标识字段,然后可以在 JOIN 的 ON 子句中使用该字段。
那么在你看来:
SELECT T1.*, T2.* FROM T1 JOIN T2 ON T1.IDFIELD1 = T2.IDFIELD2
您提到没有字段是“通用的”,但是尽管识别字段可能没有相同的名称甚至是相同的数据类型,但您可以使用 convert / cast 函数以某种方式加入它们。
你为什么不使用简单的方法
SELECT distinct *
FROM
SUPPLIER full join
CUSTOMER on (
CUSTOMER.OID = SUPPLIER.OID
)
它为您提供两个表中的所有列,如果客户有 3 条记录而供应商有 2 条记录,则返回客户和供应商的所有记录,然后供应商将在所有列中显示 NULL
Select
DISTINCT t1.col,t2col
From table1 t1, table2 t2
OR
Select
DISTINCT t1.col,t2col
From table1 t1
cross JOIN table2 t2
如果它的拥抱数据,它需要很长时间..
SELECT t1.col table1col, t2.col table2col
FROM table1 t1
JOIN table2 t2 on t1.table1Id = x and t2.table2Id = y
select * from this_table;
select distinct person from this_table
union select address as location from that_table
drop wrong_table from this_database;
当您必须使用三个选择语句执行此操作时非常困难
我尝试了所有建议的技术,但都是徒劳的
请看下面的脚本。如果您有其他解决方案,请告知
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
连接不相关的表
演示 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;
请尝试以下查询:
合并两个没有公共列的表:
SELECT *
FROM table1
UNION
SELECT *
FROM table2
ORDER BY orderby ASC