Sql server 合并两个没有公共字段的表
我想学习如何组合两个没有共同字段的db表。我查过工会,但MSDN说: 以下是使用UNION组合两个查询的结果集的基本规则:Sql server 合并两个没有公共字段的表,sql-server,union,Sql Server,Union,我想学习如何组合两个没有共同字段的db表。我查过工会,但MSDN说: 以下是使用UNION组合两个查询的结果集的基本规则: 在所有查询中,列的数量和顺序必须相同 数据类型必须兼容 但我根本没有共同的领域。我只想把它们像视图一样合并到一个表中 那么我该怎么办呢?如果表没有公共字段,那么就无法在任何有意义的视图中组合数据。您很可能最终得到一个视图,其中包含来自两个表的重复数据 SELECT * FROM table1, table2 这将把表1中的每一行与返回所有列的表2(笛卡尔积)联接起来。要获
那么我该怎么办呢?如果表没有公共字段,那么就无法在任何有意义的视图中组合数据。您很可能最终得到一个视图,其中包含来自两个表的重复数据
SELECT *
FROM table1, table2
这将把表1中的每一行与返回所有列的表2(笛卡尔积)联接起来。要获得这两个表的有意义/有用的视图,通常需要从每个表中确定一个标识字段,然后在联接中的ON子句中使用该字段 那么在你看来,
SELECT T1.*, T2.* FROM T1 JOIN T2 ON T1.IDFIELD1 = T2.IDFIELD2
您提到没有字段是“通用”的,但尽管标识字段可能没有相同的名称,甚至不是相同的数据类型,但您可以使用转换/转换函数以某种方式将它们连接起来。这是一个非常奇怪的请求,几乎可以肯定这是您在实际应用程序中永远不想做的事情,但从纯学术的角度来看,这是一个有趣的挑战。在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
这是可行的,但它非常愚蠢,我只提供了一个“社区维基”答案,因为我真的不推荐它。有很多方法可以做到这一点,这取决于你真正想要什么。由于没有公共列,您需要决定是引入公共列还是获取产品 假设您有两张桌子:
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个客户将导致100000行中包含大量重复信息 或者,您可以使用union仅输出数据,但不能并排输出(您需要确保两个select之间的列类型兼容,方法是使表列兼容或在select中强制它们): 在某些数据库中,可以使用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)都有一个单独的数据表。为什么不使用简单的方法
SELECT distinct *
FROM
SUPPLIER full join
CUSTOMER on (
CUSTOMER.OID = SUPPLIER.OID
)
它提供两个表中的所有列,并返回客户和供应商的所有记录。如果客户有3条记录,供应商有2条记录,则供应商将在所有列中显示空值。请尝试此查询:
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 table1
UNION
SELECT *
FROM table2
ORDER BY orderby ASC
如果是拥抱数据,则需要很长时间。尝试:
select * from table 1 left join table2 as t on 1 = 1;
这将使两个表中的所有列都显示出来。如果必须使用三个select语句执行此操作,将非常困难 我尝试了所有提议的技术,但都没有成功 请看下面的脚本。如果您有其他解决方案,请提供建议
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
选择不同的x.有史以来最好的,y.今天最好的,z.最违反者
(选择(按tl.username排序)上方的第(4)行作为conj,tl。
[username]+'-->'+str(count(*)是有史以来最好的
来自[TiketFollowup].[dbo].N\u FCR\u Tikect\u Log\u Archive tl
按tl.username分组
按计数排序(*)说明)x
左外连接
(选择
顶部(4)行(按tl.username排序)为conj,tl.[username]+'-->'+str(count(*)为当前最佳
来自[TiketFollowup].[dbo].[N_FCR_Tikect_Log]tl
其中convert(date,tl.stamp,121)=convert(date,GETDATE(),121)
按tl.username分组
按计数排序(*)说明)y
关于x.conj=y.conj
左外连接
(
选择(按计数(*)排序)上的行数()作为conj,username+'-->'+str(count(dbo.isincreated(stamp)))作为N\u FCR\u票证中的最违反者
其中dbo.isIncreated(stamp)=“increated”和convert(date,stamp,121)
连接不相关的表
演示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;
为了连接不相关的表,我们将介绍一个常见的序列号连接列,如下所示
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 table 1 left join table2 as t on 1 = 1;
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
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;
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;