【问题标题】:MIN(DATE) not working in SQL ServerMIN(DATE) 在 SQL Server 中不起作用
【发布时间】:2018-05-25 04:48:36
【问题描述】:

我正在使用 SSMS 查询 SQL Server 2012。我需要 NPH 表中最早 STARTDATE 的记录。如果我有一个客户的行具有相同的开始日期,我会得到一行。但是对于具有不同开始日期的行的客户,我根本没有得到任何结果。为什么它没有从 PLACEMENTHISTORY 表中恢复 min(startdate)?

select distinct lsf.CLIENTNUMBER
,nph.ENDDATE
,nph.STARTDATE
from legalstatusform lsf
left join PLACEMENTHISTORY nph on nph.CLIENTNUMBER = lsf.clientnumber
and (nph.STARTDATE = (select min(startdate) from PLACEMENTHISTORY x
                where x.CLIENTNUMBER = nph.CLIENTNUMBER))
where nph.ENDDATE >= '2017-05-01'
and nph.ENDDATE <= '2017-05-31'
and nph.CLIENTNUMBER = '2001'
group by lsf.CLIENTNUMBER, lsf.ENDDATE, nph.STARTDATE, nph.ENDDATE

这个逻辑根本没有给我任何结果

如果我注释掉 min(startdate) 逻辑,我会得到这个客户端的 3 行数据。开始日期为 2017 年 1 月 31 日、2017 年 4 月 11 日和 2017 年 5 月 10 日。那么对于 min(startdate) 逻辑,为什么我不能只得到 1/31/2017 startdate 的第 1 行?

【问题讨论】:

  • 它不能返回任何结果,因为该用户的MIN 子查询返回另一个日期(不是这三个日期之一)...
  • 对,呵呵。我说错了。我应该得到 2017 年 5 月 10 日的日期,但不是没有结果,对吧?

标签: sql sql-server min


【解决方案1】:

尝试使用 CTE,而不是使用子查询(并解析表两次)。排序最终可能会同样昂贵,具体取决于您的索引:

WITH CTE AS(
    SELECT lsf.CLIENTNUMBER,
           nph.ENDDATE,
           nph.STARTDATE,
           ROW_NUMBER() OVER (PARTITION BY lsf.CLIENTNUMBER ORDER BY nph.STARTDATE) AS RN
    FROM legalstatusform lsf
    LEFT JOIN PLACEMENTHISTORY nph ON nph.CLIENTNUMBER = lsf.clientnumber
    WHERE nph.ENDDATE >= '2017-05-01'
      AND nph.ENDDATE <= '2017-05-31'
      AND nph.CLIENTNUMBER = '2001'
    GROUP BY lsf.CLIENTNUMBER, lsf.ENDDATE, nph.STARTDATE, nph.ENDDATE)
SELECT *
FROM CTE
WHERE RN = 1;

【讨论】:

  • 那行得通,我从未使用过 CTE。现在我的问题是此代码将进入 SSRS 中的报告,并且 Enddate 是一个声明的参数,它不适用于此。我可以在 CTE 中使用声明的参数吗?
  • 是的,只需像往常一样在WHERE 子句中的CTE 中使用它。
  • 我试过了,它没有用,但我发现另一个帖子说你必须在它后面添加一个分号,它现在可以工作了......哇哦,谢谢你的帮助!
  • 是的,WITH 要求您终止(之前的)SQL 语句。不推荐使用; 终止您的SQL 语句,因此无论如何最好这样做;尤其是在引入使其成为强制性的功能时。
【解决方案2】:

select distinct 几乎不适合与group by

您的问题是where 子句中的条件。这些将外部连接变成了内部连接。试试这个:

select distinct lsf.CLIENTNUMBER, nph.ENDDATE, nph.STARTDATE
from legalstatusform lsf left join
     PLACEMENTHISTORY nph
     on nph.CLIENTNUMBER = lsf.clientnumber and
        nph.STARTDATE = (select min(startdate)
                         from PLACEMENTHISTORY x
                         where x.CLIENTNUMBER = nph.CLIENTNUMBER)
                        ) and
        nph.ENDDATE >= '2017-05-01' and
        nph.ENDDATE <= '2017-05-31'
where lsf.CLIENTNUMBER = '2001';

注意事项:

  • 您可能需要子查询中ENDDATE 的条件。
  • 我会选择窗口函数而不是这种形式的查询。
  • 如果CLIENTNUMBER 是一个数字,那么'2001' 不应有引号。

【讨论】:

  • 你给我的代码给了我一个结果,但是ENDDATE和STARTDATE都是NULL
  • @SheriAnderson 。 . .一点也不奇怪。您可能还想在子查询中按日期过滤。
【解决方案3】:

因为您使用 MIN() 的子查询不具备此条件:

where nph.ENDDATE >= '2017-05-01'
and nph.ENDDATE <= '2017-05-31'

只运行子查询

select min(startdate) from PLACEMENTHISTORY
where x.CLIENTNUMBER = '2001'

并查看带有 MIN() startdate 的行是否与外部查询中的过滤器匹配。

【讨论】:

  • 谢谢!我添加了 x.ENDDATE >= '2017-05-01' 和 x.ENDDATE
  • 该死。它适用于编写此查询,但此查询将在 SSRS 报告中,并且我的日期是参数。显然我不能在子查询中使用声明的参数?当我为参数添加@StartDate 时,我再次没有得到任何结果。有什么想法吗?
  • 不,它没有,我明白你在说什么,但我需要日期中的 min(startdate) 作为参数。
猜你喜欢
  • 2014-05-21
  • 1970-01-01
  • 2017-06-12
  • 2017-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-08
  • 2011-07-22
相关资源
最近更新 更多