【问题标题】:Results of UNION Selects in SQL ServerSQL Server 中 UNION 选择的结果
【发布时间】:2023-03-22 07:44:01
【问题描述】:

是否可以对没有任何共同结果的表或视图进行 UNION 查询?我正在尝试做的是将来自不同视图的数据组合成一个结果。我有

select a,b,null,c from VIEW1, VIEW2 where VIEW1.a = VIEW2.a
UNION
select null,null,z,null from VIEW3

我希望结果是 a,b,z,c。这是我会使用 select from 的地方吗?那是什么样子的?

select ? from (
select a,b,null,c from VIEW1, VIEW2 where VIEW1.a = VIEW2.a
UNION
select null,null,z,null from VIEW3)

我使用的是 MS SQL Server,视图没有主键。非常感谢。

【问题讨论】:

  • 是的,有可能,是什么阻止您尝试这个?做的时候是不是不行?
  • 只需使用 * 代替 ?在您的第二个查询中。
  • @Rashack:这将产生与第一个查询相同的结果...

标签: sql-server select union


【解决方案1】:

如果我理解这一点:您是否试图“折叠”您的结果并摆脱所有 NULL?如果是这样,view3 的结果是否会对应于 view1/view2 的结果?如果有,是什么关系?如果不是,结果的数量是否至少匹配?

【讨论】:

  • 我使用 NULL 作为占位符,理解为在 UNION 中,结果集必须具有相同的列数。我确实有 View1.z,但是当我把它放在第一个查询的 where 子句中时,我丢失了 View1 中的所有行,其中 View3 中没有匹配的行——我需要那些 View1 行!无论 View3 中是否存在匹配项,我都需要 View1 中的所有结果行,但是当我尝试使用外部联接的单个查询时,我外部联接了 View1 和 View2,然后再次使用 View3 进行外部联接。也许我应该再次尝试使用 2 个外部连接的 1 个查询?
【解决方案2】:

您可能正在寻找这样的东西吗? (只是一个疯狂的猜测)

SELECT 
  VIEW1.a,
  VIEW1.b,
  (SELECT TOP 1 z FROM VIEW3) AS z,
  VIEW2.c
FROM
  VIEW1, VIEW2 
WHERE
  VIEW1.a = VIEW2.a

【讨论】:

    【解决方案3】:

    如果我理解您的问题,您可能会得到如下结果:

    a1, b1, null, c1
    a2, b2, null, c2
    a3, b2, null, c3
    null, null, z1, null
    null, null, z2, null
    null, null, z3, nul
    

    l

    .. 但是你想要得到的是这样的结果:

    a1, b1, z1, c1
    a2, b2, z2, c2
    a3, b2, z3, c3
    

    我是否正确理解了这个问题?

    如果这是正确的,您将需要有一种方法将这些子查询连接在一起,这样您就可以告诉 SQL 1 一起去,2 一起去,等等。

    【讨论】:

    • 是的——你明白了!所以,这就是我的问题:有没有初学者加入查询的方法?我确实在 View1 中有 z,但是当我将它作为 View1.z = View3.z 放入原始单个查询中时,我丢失了 View1 中没有匹配的所有行——我需要所有即使 z 上没有匹配项,也从 View1 返回的行。我在 View、View2 上尝试了外部连接,我总是在其中获得成功,然后在 View3 上再次尝试 OJ,但这似乎不起作用。当我切换到 2 个查询时,我使用 NULL 作为占位符,因为联合中的所有查询中的列数必须相同,对吧?
    • 您可以尝试从 View1.z 到 View3.z 的 LEFT OUTER join 吗?这将允许您查看视图 1 和 3 中的内容,同时仍为您提供一种方法,将来自 View3 的内容链接到它们所属的行中。
    【解决方案4】:

    联合连接结果集,它不合并它们。

    所以你会从你的第一个查询中得到:

      a      b    (null)  c
    (null) (null)   z    (null)
    

    如果你想组合它们,你必须加入它们,然后你需要有一些共同点,或者你必须在程序中组合数据。

    每个人只有 1 行吗?

    如果是这样,那么如果上面的模式总是这样,这将起作用:

    SELECT SQ1.a, SQ1.b, SQ2.z, SQ1.c
    FROM (
        SELECT 1 k, View1.a, b, NULL z, c
        FROM View1 INNER JOIN View2 ON View1.a = View2.a) SQ1
    INNER JOIN (
        SELECT 1 k, NULL a, NULL b, z, NULL c
        FROM View3) SQ2 ON SQ1.k = SQ2.k
    

    但是,如果您不知道 View3.a 是否具有值或 View1.a 是否具有值,并且您希望第一个查询中的值是否为 3,那么这将起作用:

    SELECT COALESCE(SQ1.a, SQ2.a) a, COALESCE(SQ1.b, SQ2.b) b,
        COALESCE(SQ1.z, SQ2.z) z, COALESCE(SQ1.c, SQ2.c) c
    FROM (
        SELECT 1 k, View1.a, b, NULL z, c
        FROM View1 INNER JOIN View2 ON View1.a = View2.a) SQ1
    INNER JOIN (
        SELECT 1 k, NULL a, NULL b, z, NULL c
        FROM View3) SQ2 ON SQ1.k = SQ2.k
    

    但是,这里有一个很大的 BUT。如果您在任一视图中有不止一行,您最终会得到不属于一起的数据。在这种情况下,您必须有一些共同点。

    这是我尝试过的完整代码以及结果:

    USE master
    GO
    
    DROP DATABASE TestDB
    GO
    
    CREATE DATABASE TestDB
    GO
    
    USE TestDB
    GO
    
    CREATE TABLE View1
    (
        a INT,
        b INT,
        c INT
    )
    GO
    
    CREATE TABLE View2
    (
        a INT,
        z INT
    )
    GO
    
    CREATE TABLE View3
    (
        z INT
    )
    GO
    
    INSERT INTO View1 (a, b, c) VALUES (10, 20, 30)
    GO
    
    INSERT INTO View2 (a, z) VALUES (10, 40)
    GO
    
    INSERT INTO View3 (z) VALUES (50)
    GO
    
    
    SELECT View1.a, b, NULL z, c
    FROM View1 INNER JOIN View2 ON View1.a = View2.a
    UNION
    SELECT NULL a, NULL b, z, NULL c
    FROM View3
    
    SELECT SQ1.a, SQ1.b, SQ2.z, SQ1.c
    FROM (
        SELECT 1 k, View1.a, b, NULL z, c
        FROM View1 INNER JOIN View2 ON View1.a = View2.a) SQ1
    INNER JOIN (
        SELECT 1 k, NULL a, NULL b, z, NULL c
        FROM View3) SQ2 ON SQ1.k = SQ2.k
    
    SELECT COALESCE(SQ1.a, SQ2.a) a, COALESCE(SQ1.b, SQ2.b) b,
        COALESCE(SQ1.z, SQ2.z) z, COALESCE(SQ1.c, SQ2.c) c
    FROM (
        SELECT 1 k, View1.a, b, NULL z, c
        FROM View1 INNER JOIN View2 ON View1.a = View2.a) SQ1
    INNER JOIN (
        SELECT 1 k, NULL a, NULL b, z, NULL c
        FROM View3) SQ2 ON SQ1.k = SQ2.k
    

    结果:

    a           b           z           c
    ----------- ----------- ----------- -----------
    NULL        NULL        50          NULL
    10          20          NULL        30
    
    (2 row(s) affected)
    
    a           b           z           c
    ----------- ----------- ----------- -----------
    10          20          50          30
    
    (1 row(s) affected)
    
    a           b           z           c
    ----------- ----------- ----------- -----------
    10          20          50          30
    
    (1 row(s) affected)
    

    如果给 View3 添加一行,像这样:

    INSERT INTO View3 (z) VALUES (51)
    

    然后你会得到这些结果,注意加倍的行:

    a           b           z           c
    ----------- ----------- ----------- -----------
    NULL        NULL        50          NULL
    NULL        NULL        51          NULL
    10          20          NULL        30
    
    (3 row(s) affected)
    
    a           b           z           c
    ----------- ----------- ----------- -----------
    10          20          50          30
    10          20          51          30
    
    (2 row(s) affected)
    
    a           b           z           c
    ----------- ----------- ----------- -----------
    10          20          50          30
    10          20          51          30
    
    (2 row(s) affected)
    

    【讨论】:

    • 我觉得我解释得不好。我在每个视图中确实有 100 行。我在 View1 中确实有 z,并且我最初使用了一个查询。但是当我将 View1.z 等同于 View3.z 并且 View3 中没有具有该 z 值的行时,我会丢失 View1 中的行。我尝试了 OUTER JOIN,但结果不正确,因此我切换到 2 个查询。如果 View3 缺少具有该 z 值的行,我在 View1 和 View3 之间没有任何共同点,所以如果我理解你的 BUT,那么我就无法做我需要做的事情。那是对的吗? (感谢您的努力。我真的很感激!)
    • 如果你没有任何共同点,你就不能加入他们,这是没有意义的。你可以伪造一些共同点,我会在今晚晚些时候回来举个例子,但这不会很好。
    【解决方案5】:

    任何 sql 选择(包括联合)的结果都是一组静态列。 (没有多态性。)

    但是您不必使用每一行中的所有列,您可以在该列没有值的行中使用空值。我还建议您包含一个“类型”行,以便客户端可以告诉给定行的类型(和有趣的列)。

    例子:

     (Select
       'room' as view_type
     , rooms.room as room
     , NULL as color
     From rooms 
     )
    UNION ALL
    (Select
      'color' as view_type
     , NULL as room
     , colors.color as color
     From colors 
    )
    

    【讨论】:

      【解决方案6】:

      你实际上想要一个交叉连接:

      从中选择 v1.a,v1.b,VIEW3.z,v1.c (从 VIEW1、VIEW2 中选择 a、b、c,其中 VIEW1.a = VIEW2.a)作为 v1 交叉连接 查看3

      【讨论】:

      • 如果我使用 CROSS JOIN,我不会得到 v1 和 VIEW3 之间的笛卡尔积吗?每个视图都有 100 行。
      【解决方案7】:


      对于多条记录,ROW_NUMBER() 方法对我有用。 Select 1 k 方法返回的是笛卡尔积。

      SELECT SQ1.a, SQ1.b, SQ2.z, SQ1.c
      FROM (
          SELECT ROW_NUMBER() OVER (ORDER BY a) k, View1.a, b, NULL z, c
          FROM View1 INNER JOIN View2 ON View1.a = View2.a) SQ1
      INNER JOIN (
          SELECT ROW_NUMBER() OVER (ORDER BY b) k, NULL a, NULL b, z, NULL c
          FROM View3) SQ2 ON SQ1.k = SQ2.k
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-05-22
        • 2023-04-08
        • 1970-01-01
        • 1970-01-01
        • 2012-08-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多