【问题标题】:SQL Downselect query results based on field duplicationSQL Downselect 基于字段重复的查询结果
【发布时间】:2012-11-03 02:45:31
【问题描述】:

我正在寻找有关 SQL 查询的一些帮助。 (我正在使用 Oracle。)

我有一个查询是 2 个不同的选择语句的联合。生成的数据如下所示:

Col1     Col2     Col3
XXX      ValA     Val1
XXX      ValB     Val2
YYY      ValA     Val1
YYY      ValA     Val2

在此设置中,Col1 = XXX 是默认值,Col1 = YYY 是实际值。实际值 (YYY) 应优先于默认值。实际值通过第 2 列和第 3 列定义。

我希望将这些结果缩减为以下内容:

Col1     Col2     Col3
XXX      ValB     Val2
YYY      ValA     Val1
YYY      ValA     Val2

请注意,第一行已被删除...这是因为有一个实际值(第 3 行中的 YYY)优先于默认值 (XXX)。

关于如何解决这个问题的任何想法?

【问题讨论】:

  • 完全不清楚是什么让 YYY 成为“真实值”而 XXX 成为“默认值”。如果没有某种方法来区分哪个是首选,您将很难做到这一点。
  • YYY 只是我通过另一个查询知道的真实姓名的占位符。 XXX 是默认值的设置字符串值。我已经解决了这个问题。谢谢。
  • 每对 Col2、Col3 是否只有一个 YYY 值,还是可能不止一个?
  • 只有 1 个 YYY 值(可能没有,在这种情况下将使用 XXX 值)
  • @typhoid:你错过了我评论的重点。如果我们不知道 XXX 是常数,则无法解决此问题,您的方案中没有说明。知道它是一个常数后,我们就可以直接对其进行测试(您会注意到所有答案都是如此)。

标签: sql oracle join union


【解决方案1】:

我的直觉是使用分析函数:

select distinct 
       first_value(col1) 
          over (partition by col2, col3 
                order by case col1 
                when 'XXX' then 1 
                else 0 end asc) as col1,
       col2, 
       col3 
from table1

但是,如果表很大并且有索引,最好使用完全外连接来解决这个问题(这是可能的,因为只有两个可能的值):

select coalesce(rl.col1, dflt.col1) as col1, 
       coalesce(rl.col2, dflt.col2) as col2,
       coalesce(rl.col3, dflt.col3) as col3
from (select * from table1 where col1 = 'XXX') dflt
full outer join (select * from table1 where col1 <> 'XXX') rl
on dflt.col2 = rl.col2 and dflt.col3 = rl.col3;

[Solution in SQLFiddle]

【讨论】:

    【解决方案2】:

    我认为你可以使用这样的技巧:

    select
      case when
      max(case when col1<>'XXX' then col1 end) is null then 'XXX' else
      max(case when col1<>'XXX' then col1 end) end as col1, 
      col2,
      col3
    from
      your_table
    group by col2, col3
    

    我将默认值转换为 null,然后按 col3 分组。 null 和 value 之间的最大值是您要查找的值。这适用于您的示例数据,但它可能不是您要查找的内容,这取决于您的真实数据。

    【讨论】:

      【解决方案3】:

      您想过滤掉 col2 和 col3 出现的所有行,其中包含 XXX 和另一个值。

      您可以通过使用分析函数在子查询中进行适当的计数来实现此过滤器:

      select col1, col2, col3
      from (select t.*,
                   count(*) over (partition by col2, col3) as numcombos,
                   sum(case when col1 = 'XXX' then 1 else 0 end) over (partition by col2, col3) as numxs
            from t
           ) t
      where numcombos = numxs or (col1 <> 'xxx')
      

      【讨论】:

        猜你喜欢
        • 2020-08-28
        • 1970-01-01
        • 2023-03-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-29
        • 1970-01-01
        相关资源
        最近更新 更多