我想学习如何组合两个没有共同字段的db表。我已经检查了UNION,但是MSDN说:
以下是使用UNION组合两个查询的结果集的基本规则:
- 所有查询中列的数量和顺序必须相同。
- 数据类型必须兼容。
醇>
但我根本没有共同的领域。我想要的只是将它们组合在一个表中,就像一个视图。
那我该怎么办?
提前致谢。
此致。
答案 0 :(得分:108)
有很多方法可以执行此操作,具体取决于您 想要的内容。如果没有常用列,则需要确定是要引入公共列还是获取产品。
假设您有两个表:
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行,其中包含大量重复信息。
或者,您可以使用union来输出数据,但不能并排(您需要确保两种选择之间的列类型兼容,方法是使表列兼容或强制它们在选择中):
> 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
在某些数据库中,您可以使用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并排放置。
如果您只是希望它们在报告或网页上并排显示(两个示例),那么正确的工具就是生成报告或网页的任何内容,再加上两个独立< / em> SQL查询以获取两个不相关的表。例如,BIRT(或Crystal或Jasper)中的两列网格,每个网格都有一个单独的数据表,或者一个HTML二列表(或CSS),每个都有一个单独的数据表。
答案 1 :(得分:22)
这是一个非常奇怪的请求,几乎可以肯定,在现实世界的应用程序中你永远不想做的事情,但从纯粹的学术角度来看,这是一个有趣的挑战。使用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
这很有效,但它非常愚蠢,我只是作为一个“社区维基”答案,因为我真的不推荐它。
答案 2 :(得分:11)
SELECT *
FROM table1, table2
这会将table1中的每一行与table2(笛卡尔积)一起返回所有列。
答案 3 :(得分:3)
如果表没有公共字段,则无法在任何有意义的视图中组合数据。您最终可能会得到一个包含来自两个表的重复数据的视图。
答案 4 :(得分:2)
要获得两个表的有意义/有用的视图,通常需要确定每个表中的标识字段,然后可以在JOIN的ON子句中使用该标识字段。
在你看来:
SELECT T1.*, T2.* FROM T1 JOIN T2 ON T1.IDFIELD1 = T2.IDFIELD2
您提到没有字段是“常见的”,但是虽然标识字段可能不具有相同的名称,甚至可能是相同的数据类型,但您可以使用convert / cast函数以某种方式连接它们。
答案 5 :(得分:2)
为什么不使用简单的方法
SELECT distinct *
FROM
SUPPLIER full join
CUSTOMER on (
CUSTOMER.OID = SUPPLIER.OID
)
它为您提供了来自两个表的所有列,并返回来自客户和供应商的所有记录,如果客户有3条记录且供应商有2条,则供应商将在所有列中显示NULL
答案 6 :(得分:2)
Select
DISTINCT t1.col,t2col
From table1 t1, table2 t2
OR
Select
DISTINCT t1.col,t2col
From table1 t1
cross JOIN table2 t2
如果它的拥抱数据,它需要很长时间..
答案 7 :(得分:2)
尝试:
select * from table 1 left join table2 as t on 1 = 1;
这将带来两个表中的所有列。
答案 8 :(得分: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;
答案 9 :(得分:1)
SELECT t1.col table1col, t2.col table2col
FROM table1 t1
JOIN table2 t2 on t1.table1Id = x and t2.table2Id = y
答案 10 :(得分: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;
答案 11 :(得分: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
答案 12 :(得分: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;
答案 13 :(得分:-2)
请尝试此查询:
合并两个没有公共列的表:
SELECT *
FROM table1
UNION
SELECT *
FROM table2
ORDER BY orderby ASC