【问题标题】:Union of two tables but show which table the data came from两个表的并集,但显示数据来自哪个表
【发布时间】:2012-08-24 10:58:18
【问题描述】:

我有两张桌子:

           TABLE_A                 TABLE_B
Fields:    Trans   Amend           Trans   Amend 
data:      100       0             100      0
           100       1
           110       0         
                                   120      0
                                   120      1
           130       0             130      0 
                                   130      1
           140       0             140      0
           150       0             150      0
           150       1             150      1
           150       2             

我想要的是一个表格(视图),它将把这些组合(联合)到表格中,但只会显示每个 Trans 的最高修正

寻找这个作为答案:

Fields:    Trans   Amend   
data:      100       1
           110       0
           120       1
           130       1
           140       0 
           150       2   

然后更难,我想知道是否有一种方法可以告诉我数据来自哪个表。当记录 A 和记录 B 相等时,表 A 总是获胜 寻找这个作为答案:

Fields:    Trans   Amend    WhichTBL
data:      100       1      Table_A
           110       0      Table_A
           120       1      Table_B
           130       1      Table_B
           140       0      Table_A
           150       2      Table_A

我知道无法使用 UNION 来获得此结果。

【问题讨论】:

  • 接受的答案可能会返回错误的结果。应改用 Carlos A. Ibarra 的解决方案。
  • 在实际解决问题后,我更新了我的答案。请重新考虑。

标签: sql union highest


【解决方案1】:

如果您在选择中添加了一个字符串并将其别名为列怎么办?

SELECT Trans, Amend, 'Table_A' as WhichTBL
FROM (your 1st select query)
UNION
SELECT Trans, Amend, 'Table_B' as WhichTBL
FROM (your 2nd select query)
ORDER BY Trans

【讨论】:

    【解决方案2】:

    如果 Amend 只有值 1 和 0 那么第一个问题就可以做完了

    select Trans,sum(Amend) AmendMax from (select Trans,Amend from TABLE_A
    union select Trans,Amend from TABLE_B) C group by Trans
    

    第二个问题是

    select Trans,max(Amend) Amend,case when sum(s)=1 or  sum(s)=2 or  sum(s)=21 
    then 'Table-A' when sum(s)=10 or  sum(s)=12 or sum(s)=20  then 'Table-B' 
    when sum(s)=11 or  sum(s)=22 then 'Table-A and B' end s from 
    (select case when max(Amend)=1 then 1 else 2 end s,Trans,max(Amend) Amend from TABLE_A 
    group by Trans union select case when max(Amend)=1 
    then 10 else 20 end s,Trans,max(Amend) Amend from TABLE_B group by Trans) C group by Trans
    

    【讨论】:

      【解决方案3】:

      这行得通吗?

      SELECT 
          trans, MAX(max_amend) as max_max_amend
      FROM
          (SELECT
              'a' AS src, trans, MAX(amend) AS max_amend
          FROM
              table_a
          GROUP BY
              trans
      
          UNION ALL
      
          SELECT
              'b' AS src, trans, MAX(amend) AS max_amend
          FROM
              table_b
          GROUP BY
              trans) m
      GROUP BY
          trans
      

      Lucero 的以下观点是正确的,min(src) 将在全局集上,而不是相关的 max()

      我认为您必须将源值和表值组合到一列中,您可以最大化。在您的示例中,只需将值加 1 即可区分来源,例如:

      SELECT trans, Max(amend) AS MaxOfamend, 1+[amend] AS isa, 0 AS isb
      FROM TableA
      GROUP BY trans
      

      但您可以加 100,或乘以一个大值,或任何适用于您的数据的方法。想法是将两条信息(修改值和来源)合并为一列。

      然后,在组合信息之后,您会得到该值的最大值,然后通过取消组合来去除源标志(减去 1,除以 100,等等)


      好的,这就是我得到的:

      CREATE VIEW [dbo].[viewA]    AS
      SELECT trans, MAX(amend + .20) AS srcIsA, 0 AS srcIsb
      FROM  dbo.tableA
      GROUP BY trans
      
      CREATE VIEW [dbo].[viewB]    AS
      SELECT trans, 0 AS srcIsA, MAX(amend + .10) AS srcIsB
      FROM  dbo.tableB
      GROUP BY trans
      
      CREATE VIEW [dbo].[viewU]    AS
      SELECT * from viewA
      union all
      select *
      FROM  viewb
      
      CREATE VIEW [dbo].[viewv]    AS
      SELECT trans, srcIsA, srcIsb, srcIsA + srcIsb AS total
      FROM  dbo.viewU
      
      CREATE VIEW [dbo].[vieww]    AS
      SELECT trans, MAX(total) AS max_total
      FROM  dbo.viewv
      GROUP BY trans
      
      CREATE VIEW [dbo].[viewx] AS
      SELECT trans, 
      max_total, 
      CAST(max_total AS int) AS maxval, 
      CASE WHEN (max_total - CAST(max_total AS int)) = .1 THEN 'a' ELSE 'b' END AS src
      FROM  dbo.vieww
      

      【讨论】:

      • GROUP BY 不会削减它 - MAX(max_amend) 可能来自与 MIN(src) 不同的行(因此来自不同的源表) - 因此该行的(真实)起源将丢失(例如,您将在示例中将 trans 130 归因于表 A 的修改 1)。
      【解决方案4】:

      在 Teradata SQL 中,您将执行以下操作,但不确定 SQL Server:

      select trans,amend,WhichTBL from
      (
      select trans,amend,'Table_A' WhichTBL from Table_A
      union
      select trans,amend,'Table_B' WhichTBL from Table_B
      ) X
      qualify row_number() over(partition by trans order by amend desc, WhichTBL) = 1
      order by trans;
      

      如果您的 SQL 没有 QUALIFY 子句,则使用 Lucero 建议的版本:

      select trans,amend,WhichTBL from
      (
         select x.*,row_number() over(partition by trans order by amend desc, WhichTBL) as rn
         (
            select trans,amend,'Table_A' as WhichTBL from Table_A
            union
            select trans,amend,'Table_B' as WhichTBL from Table_B
         ) Derived1 as X
      ) Derived2
      where rn = 1
      order by trans;
      

      【讨论】:

      • QUALIFY 子句并非在所有数据库系统中都存在,但很容易通过使用暴露ROW_NUMBER() 的嵌套查询来模拟,然后使用WHERE 子句过滤此查询。
      • 这应该被标记为正确答案。但是,最好将 union 更改为 union all (因为行永远不会相同,因此没有必要对它们进行重复数据删除)。
      【解决方案5】:

      我想提供的是,您可以使用标准 SQL 进行连接和聚合:

      select coalesce(a.trans, b.trans) as trans,
             (case when coalesce(max(b.amend), -1) > coalesce(max(a.amend), -1)
                   then max(b.amend)
                   else max(a.amend)
              end) as amend,
             (case when coalesce(max(b.amend), -1) > coalesce(max(a.amend) , -1)
                   then 'B' else 'A'
              end) as whichTable
      from Table_A a full outer join
           Table_B b
           on a.trans = b.trans
      group by coalesce(a.trans, b.trans)
      

      【讨论】:

      • Buggy: 每当a.amend 为NULL 时(由于完全外连接只找到b.trans),您的MAX(a.amend) 也将为NULL,因此条件max(b.amend) > max(a.amend) 将返回false,然后它会选择“A”表值和标识符,尽管它是 NULL(哦,还要注意 'A" 字符串文字上的语法错误)。
      • @Lucero 。 .准确地说,max(a.amend) 或 max(b.amend) 需要为 NULL 才能发生故障(细微差别是数据中的 amend 为 NULL 时)。无论如何,我解决了这个问题,假设在数据中修正总是非负的(就像在示例数据中一样)。
      • max(b.amend) 为 NULL 的情况下,它会(无意中?)起作用,因为案例的 ELSE 部分将是正确使用的部分 - 这就是为什么我只指出另一个。
      猜你喜欢
      • 1970-01-01
      • 2016-08-30
      • 2014-10-15
      • 1970-01-01
      • 1970-01-01
      • 2012-04-04
      • 1970-01-01
      • 1970-01-01
      • 2022-01-03
      相关资源
      最近更新 更多