【问题标题】:Compare dates in table where similar columns are in different rows比较表中相似列位于不同行中的日期
【发布时间】:2018-06-20 19:01:05
【问题描述】:

SQL Server 2008/12 问题。我会尽量做一个简单的解释。

有一张数据表

  • 第 1 列包含 id,5 个字符,
  • 第二列包含代码,1 个字符(始终 = 1 或 2)
  • 第三列包含 YYYYmmdd 格式的日期

像这样:

create table #temp 
(
     id varchar (5),
     code varchar (3),
     dt varchar(8)
)

insert into #temp (id,code,dt)
values ('abc00', '2', '20180101'), ('abc01', '1', '20180201'),
       ('def00', '1', '20180201'), ('def01', '2', '20180101'),
       ('ghi00', '2', '20180101'), ('ghi01', '1', '20180102'),
       ('jkl00', '1', '20180101')

我需要一个或多个执行以下操作的选择查询:

对于整个表格,如果 id 的前 3 个字符相等,则它们是“相关”id(left(id, 3) 相同)

因此,对于每个“集合”的相关 id 找到 min(id)max(id),然后确保 min(id).date < max(id).date

我已经尝试过涉及OVER(PARTITION id)、CTE 自连接和临时表的答案,但我不知道如何将它们组合在一起以使其工作。

我似乎在寻找相关 id 的不同行时卡住了。

我正在比较每个相关 id 的日期,找出哪个更大。如果我能得到它的工作,我想我可以把它带回家。

我从另一个线程 (Compare dates between 2 different rows and columns) 获得了一些帮助,但是限制当前行和所有“相关” id 之间的搜索所增加的复杂性让我很难过,这就是我认为我要崩溃的地方。

这是我目前所得到的:

select * 
from #temp 
where cast(dt as date) > (select top 1 cast(dt as date) 
                          from #temp AS sub
                          where sub.id in (select id 
                                           from #temp 
                                           where (left(#temp.id, 3) = left(sub.id, 3)) 
                                             and (#temp.id <> sub.id)) 
                          order by id)  

... 但这不会返回任何行。我整天都在努力解决这个问题。

编辑

作为我在这里期待的一个例子:

使用这个 stmt:

select * 
from #temp sub 
where 'abc' = left(sub.id, 3) and ('abc01' <> sub.id)

我得到这个结果:

id    code dt
----- ---- --------
abc00 2    20170101

感谢@Philip 的编辑提示

谁能帮忙?

感谢阅读。

【问题讨论】:

  • 表格有Columns Fields
  • 您能否提供一个您期望的结果的模型?
  • 题外话:根据您的描述,您应该考虑重新设计表结构。也许您应该将列 id 拆分为 2 列:前 3 个字符是字符串,第二个是 int 值。这可能会让您大大提高性能
  • 我在这里看到的第一个问题是您将日期存储为字符串。为什么这么多人这样做,我无法理解。我们有日期和日期时间数据类型是有原因的。使用它们。 sqlblog.org/2009/10/12/…
  • 不要永远Date存储为String,使用Date/DateTime数据类型。

标签: sql sql-server


【解决方案1】:

我想你想要这个?

select * from #temp 
        where cast(dt as date) > 
            (select TOP 1 cast(dt as date) from #temp AS sub
                where (left(sub.id,3)) in 
                ( 
                    select (left(id,3)) AS Id from #temp where (left(#temp.id,3) = left(sub.id,3))  AND #temp.id  != sub.id 
                ) 
            )

【讨论】:

  • 噢!妈呀!你今天赢得了互联网。就是这样。我不敢相信我离得那么近。我把这篇文章推迟了好几个小时,把它全部写出来就让我完成了 95% 的工作。非常感谢!干杯!戴夫
  • 希望我能支持你。我还是个新手,没有足够的业力。但我确实给了你答案!再次感谢您!
【解决方案2】:

这样的?

select
    grp = left(id, 3),
    MinDt = min(dt),
    MaxDt = max(dt)
from #temp
group by left(id, 3)
having min(dt) < max(dt)

【讨论】:

  • 如果你想比较它们,你必须将字符串转换为日期(当这些是字符串并且你想要根据日期的 min/max 时, min(dt)
  • 我没有解决他没有问的问题。足够多的 cmets 连接到 OP 以驱动该点回家。
  • 另外,它看起来日期数据是 YYYYMMDD 格式,所以最小/最大比较应该是有效的。当然,假设数据是有效且一致的。
  • 谢谢。我编辑了 OP 以显示我对每一行的期望。如果这是另一种语言,我可以调试它以查看在内部选择期间 #temp.id 和 sub.id 持有什么,但在 mssql 中当然不能这样做。
猜你喜欢
  • 2019-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多