【问题标题】:SQL: return only those columns with different dataSQL:只返回那些具有不同数据的列
【发布时间】:2011-02-11 17:11:28
【问题描述】:

我有两行来自一个有很多列的表。如何只返回 row1 的值不等于 row2 的那些列?

我使用的是 Oracle 11.1.0.07

~~ 编辑:澄清~~

示例: 所以我有一个有行的表:

1 a b c d e f g h i j k l
2 a x c d e x g h y j k l
3 a b x d e x g h x y k z

我想返回 id(第一列)为 1 或 3 的行,只返回那些不同的列。所以:

1 c f i j l
3 x x x y z

带有列名。

实际上,我从中提取的表有 223007 行和 40 列。上面是一个简化的例子。我要比较两行(每行用于主键值)。

【问题讨论】:

  • 请稍微澄清一下您的问题。您是否尝试选择 DISTINCT 行?
  • 关系数据库的表中没有row 1这样的东西。而且我不明白你为什么说“row1 的值”。你的意思是:一行的所有列都不同于另一行的所有列?请向我们展示一些示例数据和预期输出
  • 我认为您要做的是转置(或转置)两个明确定义的行,然后仅选择那些列(在转置后变为行) ,它们具有不同的值...
  • 为什么不包括第 2 行?。第 10 列在所有行上都是唯一的,但只返回 jy
  • @Thomas 实际上,我的表有数十万行。我只想找出两行之间的差异。

标签: sql oracle oracle11g


【解决方案1】:

首先,SQL 语言不是为动态列生成而设计的。为此,您需要编写应该在中间层或报告组件中完成的动态 SQL。

其次,如果您要比较两个特定的行,那么最简单的解决方案可能是返回这些行并在中间层组件中分析它们。但是,如果您接受我们必须返回所有列并且您坚持在 SQL 中这样做,这是一种解决方案:

With Inputs As
    (
    Select 1 As Col1,'a' As Col2,'b' As Col3,'c' As Col4,'d' As Col5,'e' As Col6,'f' As Col7,'g' As Col8,'h' As Col9,'i' As Col10,'j' As Col11,'k' As Col12,'l' As Col13
    Union All Select 2,'a','x','c','d','e','x','g','h','y','j','k','l'
    Union All Select 3,'a','b','x','d','e','x','g','h','x','y','k','z'
    )
    , TransposedInputs As
    (
    Select Col1, 2 As ColNum, Col2 As Value From Inputs
    Union All Select Col1, 3, Col3 From Inputs
    Union All Select Col1, 4, Col4 From Inputs
    Union All Select Col1, 5, Col5 From Inputs
    Union All Select Col1, 6, Col6 From Inputs
    Union All Select Col1, 7, Col7 From Inputs
    Union All Select Col1, 8, Col8 From Inputs
    Union All Select Col1, 9, Col9 From Inputs
    Union All Select Col1, 10, Col10 From Inputs
    Union All Select Col1, 11, Col11 From Inputs
    Union All Select Col1, 12, Col12 From Inputs
    Union All Select Col1, 13, Col13 From Inputs
    )
    , UniqueValues As
    (
    Select Min(Col1) As Col1, ColNum, Value
    From TransposedInputs
    Where Col1 In(1,3)
    Group By ColNum, Value
    Having Count(*) = 1
    )
Select Col1
    , Min( Case When ColNum = 2 Then Value End ) As Col2
    , Min( Case When ColNum = 3 Then Value End ) As Col3
    , Min( Case When ColNum = 4 Then Value End ) As Col4
    , Min( Case When ColNum = 5 Then Value End ) As Col5
    , Min( Case When ColNum = 6 Then Value End ) As Col6
    , Min( Case When ColNum = 7 Then Value End ) As Col7
    , Min( Case When ColNum = 8 Then Value End ) As Col8
    , Min( Case When ColNum = 9 Then Value End ) As Col9
    , Min( Case When ColNum = 10 Then Value End ) As Col10
    , Min( Case When ColNum = 11 Then Value End ) As Col11
    , Min( Case When ColNum = 12 Then Value End ) As Col12
    , Min( Case When ColNum = 13 Then Value End ) As Col13
From UniqueValues
Group By Col1

结果:

Col1 | Col2 | Col3 | Col4 | Col5 | Col6 | Col7 |科尔8 |科尔9 | Col10 | Col11 | Col12 | Col13 1 |空 |空 | c |空 |空 | f |空 |空 |我 | j |空 | l 3 |空 |空 | x |空 |空 | x |空 |空 | x |是 |空 | z

【讨论】:

  • 不优雅,但我知道优雅是不可能的。谢谢!
【解决方案2】:

如果您尝试将第 1 行和第 2 行转置转置列,那么这些问题可能会对您有所帮助:

旋转后,您只能选择那些具有row1_pivoted <> row2_pivoted的元组

【讨论】:

  • 此外,检查您的其他问题:stackoverflow.com/questions/2140377/…,您确实有一些复杂的任务! :)
  • 我们只有一些包含很多列的表,所以很难只用眼睛看,看看结果......
【解决方案3】:

嗯。当我重新阅读问题时,第一次回答是错误的。所以......为了澄清,你有一些行/值

  1. a b c
  2. d e f
  3. a b c

并且您只希望返回“d e f”行,因为它在其他地方没有重复的行?

【讨论】:

  • 您只能比较 where 子句中的列而不是行。
【解决方案4】:

结果集中的列数不能是动态的(不借助动态 SQL)。

您可能对Unpivot 运算符感兴趣。这将使您将列作为行返回。 我自己还没有体验过它,所以很遗憾我无法为您提供帮助:/

编辑

我想尝试一下手动旋转 :)

select *
  from inputs;

 ID C1 C2 C3 C4 C5 C6
--- -- -- -- -- -- --
  1  a  b  c  d  e  f
  2  a  x  c  d  e  x
  3  a  b  x  d  e  x 

with unpivoted as(
  select id, 'c1'  as cn, c1  as cv from inputs union all
  select id, 'c2'  as cn, c2  as cv from inputs union all
  select id, 'c3'  as cn, c3  as cv from inputs union all
  select id, 'c4'  as cn, c4  as cv from inputs union all
  select id, 'c5'  as cn, c5  as cv from inputs union all
  select id, 'c6'  as cn, c6  as cv from inputs
)
select cn
      ,max(case when id = 1 then cv end) as id1
      ,max(case when id = 3 then cv end) as id3
  from unpivoted
 where id in(1,3)
 group 
    by cn
 having count(distinct cv) = 2;


CN ID1 ID3
-- --- ---
c3   c   x
c6   f   x

上述方法通过为每一列和 ID 创建一行(2 * 6 = 12 行)。
然后我按列名(分配为文字)分组。 我总是会得到 6 个组(每列一个)。在每个组中,我将正好有两行(每个选定的 ID 一行)。
在 having 子句中,我计算了列的唯一值的数量。如果行具有相同的值,则唯一值的数量 = 1。否则我们有不匹配。

注意 1。id in(x,y) 被推送到视图中,因此我们没有选择整个表格。
注意 2. 这不能扩展到比较超过 2 行。
注 3. 这不处理任一列中的 NULLS

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-13
    • 2015-08-07
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 2020-09-11
    相关资源
    最近更新 更多