【问题标题】:Dynamic comparison of all columns for multiple rows多行所有列的动态比较
【发布时间】:2016-07-16 05:16:16
【问题描述】:

在 SQL Server 2008R2 中: 我想要做的是从同一个表中获取多行并比较它们以得出最完整的行。我需要动态的列查找,因为列可以更改并且访问我正在编写的脚本在实时时不容易更改。该表有 277 列(并且还在增加),但现在让我们尝试简化一下:

REC  FIRST  LAST   MIDDLE    CITY     STATE    CTRY
1    John   Doe              Phoenix  UNK         
2    John   Doe    Quincy             AZ
3    J      Doe              Phoenix  AZ       USA  

我希望能够选择一个“主”行,对于这个例子,我们假设 REC 1,如果值为 NULL,则从下一行中选择值,如果为空,则下一行,等所有选定的行。 奖励如果我不仅可以覆盖 NULLS,而且 value = 'UNK' 将是我的下一步。理想情况下,上述内容的组合记录应如下所示:

REC  FIRST  LAST   MIDDLE    CITY     STATE    CTRY
1    John   Doe    Quincy    Phoenix  AZ       USA

我玩弄了 EXCEPT 和各种 UNIONS,但还没有走得太远,因为它的动态方面阻碍了我的进步。

如果无法按照上面的要求对多行执行此操作,我很高兴将 1 与 2 进行比较,然后将 1 与 3 进行比较。

编辑 我正在尝试做的是动态(并且通过动态,我的意思是说列和记录数可能因出现而异)创建:

create table #Something
(
    REC int
    , FIRSTName varchar(10)
    , LASTName varchar(10)
    , MIDDLE varchar(10)
    , CITY varchar(10)
    , STATE varchar(10)
    , CTRY varchar(10)
)

insert #Something
select 1, 'John', 'Doe', NULL, 'Phoenix', 'UNK', null union all
select 2, 'John', 'Doe', 'Quincy', NULL, 'AZ', null union all
select 3, 'J', 'Doe', NULL, 'Phoenix', 'AZ', 'USA'


select
          a.REC
         ,case
            when nullif(a.FIRSTName, 'UNK') is not null then a.FIRSTName
            when nullif(b.FIRSTName, 'UNK') is not null then b.FIRSTName
            when nullif(c.FIRSTName, 'UNK') is not null then c.FIRSTName
            else                                             a.FIRSTName
          end                       FirstName
         ,case
            when nullif(a.LASTName, 'UNK') is not null then a.LASTName
            when nullif(b.LASTName, 'UNK') is not null then b.LASTName
            when nullif(c.LASTName, 'UNK') is not null then c.LASTName
            else                                            a.LASTName
          end                       LastName
         ,case
            when nullif(a.MIDDLE, 'UNK') is not null then a.MIDDLE
            when nullif(b.MIDDLE, 'UNK') is not null then b.MIDDLE
            when nullif(c.MIDDLE, 'UNK') is not null then c.MIDDLE
            else                                          a.MIDDLE
          end                       MIDDLE
         ,case
            when nullif(a.CITY, 'UNK') is not null then a.CITY
            when nullif(b.CITY, 'UNK') is not null then b.CITY
            when nullif(c.CITY, 'UNK') is not null then c.CITY
            else                                        a.CITY
          end                       CITY
         ,case
            when nullif(a.STATE, 'UNK') is not null then a.STATE
            when nullif(b.STATE, 'UNK') is not null then b.STATE
            when nullif(c.STATE, 'UNK') is not null then c.STATE
            else                                         a.STATE
          end                       STATE
         ,case
            when nullif(a.CTRY, 'UNK') is not null then a.CTRY
            when nullif(b.CTRY, 'UNK') is not null then b.CTRY
            when nullif(c.CTRY, 'UNK') is not null then c.CTRY
            else                                        a.CTRY
          end                       CTRY
     from #Something    a
         ,#Something    b
         ,#Something    c
    where a.REC = 1
      and b.REC = 2
      and c.REC = 3

【问题讨论】:

  • 你怎么知道这都是同一个人?我可以看到在大多数情况下使用 MAX,但你没有任何东西可以表明什么组成了一个组。如果你有 Jane Doe 会怎样?为什么她是约翰而不是简?也许是您发布的示例过于简化。
  • 用户决定使用哪些记录进行合并。如果表有 Jane Doe,则用户没有选择 Jane。用户选择了记录 1、2 和 3(方便)。我不一定需要潜在匹配的逻辑,而是在缩小潜在匹配范围后该怎么做。
  • 好的。那么你怎么知道应该是 John 而不是 J?
  • 用户再次确定这一点。他们选择一个主行 - 在示例中为第 1 行。仅当值为 NULL(或 UNK)时,脚本才需要考虑查看后续行。
  • 那么你需要澄清更多的事情。什么定义了后续? Rec 专栏?为什么中间名最终是“昆西”?它在任何行上都不是 NULL 或 UNK,所以它不应该是一个空字符串吗?还是您想要每列的最大值?

标签: sql sql-server unions except


【解决方案1】:

您似乎缺少一些业务规则,但这里有一个示例,至少应该为您指明正确的方向。

create table #Something
(
    REC int
    , FIRSTName varchar(10)
    , LASTName varchar(10)
    , MIDDLE varchar(10)
    , CITY varchar(10)
    , STATE varchar(10)
    , CTRY varchar(10)
)

insert #Something
select 1, 'John', 'Doe', NULL, 'Phoenix', 'UNK', null union all
select 2, 'John', 'Doe', 'Quincy', NULL, 'AZ', null union all
select 3, 'J', 'Doe', NULL, 'Phoenix', 'AZ', 'USA'

select 1
    , MAX(nullif(FIRSTName, 'UNK')) as FirstName
    , MAX(nullif(LASTName, 'UNK')) as LastName
    , MAX(nullif(MIDDLE, 'UNK')) as Middle
    , MAX(nullif(CITY, 'UNK')) as City
    , MAX(nullif(STATE, 'UNK')) as [State]
    , MAX(nullif(CTRY, 'UNK')) as Country
from #Something

【讨论】:

  • hmmm ...它不允许我对我的原件添加编辑。以上并没有真正解决这个问题的动态部分。使用示例中的填充表,查询需要是 ... select a.REC 的动态版本,当 nullif(a.FIRSTName, 'UNK') 不为空时,则为 a.FIRSTName 当 nullif(b. FIRSTName, 'UNK') is not null then b.FIRSTName when nullif(c.FIRSTName, 'UNK') is not null then c.FIRSTName else a.FIRSTName end FName ... from #Something a, #Something b, #东西 c 其中 a.REC = 1 和 b.REC = 2 和 c.REC = 3
  • 它需要在列和表数中是动态的
  • 当我发布此问题时,您的问题中缺少关于未知列数的全部内容。
【解决方案2】:

让你开始的东西。

声明

@x varchar(2) = '1' ,@sql varchar(max)

while @x

开始 set @sql = isnull(@sql,'')+ ' left join #Something x' + @x + ' on a.REC = x' + @x+'.REC - ' + @x

设置@x = @x +1 结束

set @sql =' select * from #Something a '+ @sql + ' where a.REC = 1'

执行 (@sql)

【讨论】:

  • 好的,我已将它添加到查询中,将多行转换为一行中的附加列非常酷。这将使用的列数是否有限制?与现在的其他同名列相比,我仍然不确定如何实现每列的 isnull 。我今天也在尝试一些新东西,但我认为这会派上用场,只是不确定它是否能满足我的需要。谢谢。
猜你喜欢
  • 2021-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-08
  • 2020-05-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多