Sql server 合并两个没有公共字段的表

Sql server 合并两个没有公共字段的表,sql-server,union,Sql Server,Union,我想学习如何组合两个没有共同字段的db表。我查过工会,但MSDN说: 以下是使用UNION组合两个查询的结果集的基本规则: 在所有查询中,列的数量和顺序必须相同 数据类型必须兼容 但我根本没有共同的领域。我只想把它们像视图一样合并到一个表中 那么我该怎么办呢?如果表没有公共字段,那么就无法在任何有意义的视图中组合数据。您很可能最终得到一个视图,其中包含来自两个表的重复数据 SELECT * FROM table1, table2 这将把表1中的每一行与返回所有列的表2(笛卡尔积)联接起来。要获

我想学习如何组合两个没有共同字段的db表。我查过工会,但MSDN说:

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

  • 在所有查询中,列的数量和顺序必须相同
  • 数据类型必须兼容
  • 但我根本没有共同的领域。我只想把它们像视图一样合并到一个表中


    那么我该怎么办呢?

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

    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;