SQL代码未在定义日期之前提取最高日期:已修订

时间:2016-08-25 19:38:39

标签: sql sql-server

为了清晰起见,我决定编辑此内容。

以下是我的数据表。

BLDGID,LEASID,STARTDT和BRK在表BRKP

OCCPSTAT和SUITID位于另一个名为STATUS的表中

INCATT在另一个名为BILL的表中

BLDGID  LEASID  STARTDT BRK OCCPSTAT SUITID INCCAT
  9999  100 8/5/2011    100000  C   AZ847   AVD
  9999  100 8/5/2013    200000  C   AZ847   AVD
  9999  100 8/5/2015    300000  C   AZ847   AVD
  9999  100 8/5/2017    400000  C   AZ847   AVD
  9999  250 12/1/2012   200000  C   BK497   TIL
  9999  250 12/1/2016   400000  C   BK497   TIL
  9999  250 12/7/2020   500000  C   BK497   TIL
  9999  250 1/31/2023   600000  C   BK497   TIL
  7000  987 2/19/2016       0   C   JT127   MTU
  7000  987 5/19/2020   10000   C   JT127   MTU
  7000  987 3/18/2021   20000   C   JT127   MTU
  7000  987 9/4/2023    30000   C   JT127   MTU

我想要的是为每个套件ID拉一行(每个BLDGID大约有100个独特的SUITID)。

在该行中,我需要在我定义的日期之前将STARTDT设置为最高值。

如果我定义20220831(08/31/2022),在这种情况下它应该拉一行,即第2行。

如果我定义20160831(2016年8月31日),它应该只拉第1行。

我无法弄清楚如何让它只拉一行。我可以得到很多。

我一直在尝试STARTDT =(最大(STARTDT)<' 20160831')和其他变体。

我没有输入日期的问题,它会拉7/5/2022但是,当我输入我的约会时,它什么都没有。

再次编辑:我已尝试添加以下内容,但不会更改返回的记录数。

SUITID,STARTDT DESC

选择TOP 1 *来自SUITID,STARTDT

进一步编辑:示例是该表的前4行。扩展以显示我正在使用更大的桌子。

5 个答案:

答案 0 :(得分:0)

不要在HAVING子句上按日期过滤,而是尝试使用WHERE之前的GROUP BY子句进行过滤,如下所示:

        ...

        WHERE ((SQLDATA.dbo.BRKP.STARTDT) < '20160831')
        GROUP BY SQLDATA.dbo.BRKP.BLDGID,
            SQLDATA.dbo.BRKP.LEASID,
            SQLDATA.dbo.BRKP.STARTDT,
            SQLDATA.dbo.BRKP.BRKPNT1,
            SQLDATA.dbo.LEAS.OCCPSTAT,
            SQLDATA.dbo.LEAS.SUITID,
            SQLDATA.dbo.RTBILL.INCCAT
        HAVING (
                ((SQLDATA.dbo.BRKP.BLDGID) & SPARM03)
                AND ((SQLDATA.dbo.LEAS.OCCPSTAT) = 'c')
                )

基本上,在分组之前,您只使用您感兴趣的内容对数据进行预过滤。

答案 1 :(得分:0)

我的猜测是你需要使用日期而不是字符串来处理你的HAVING子句中的不等式:

SELECT SQLDATA.dbo.BRKP.BLDGID AS 'BLDGID',
    SQLDATA.dbo.BRKP.LEASID AS 'LEASID',
    SQLDATA.dbo.BRKP.STARTDT AS 'STARTDT',
    SQLDATA.dbo.BRKP.BRKPNT1 AS 'BRKPNT1',
    SQLDATA.dbo.LEAS.OCCPSTAT AS 'OCCPSTAT',
    SQLDATA.dbo.LEAS.SUITID AS 'SUITID',
    SQLDATA.dbo.RTBILL.INCCAT AS 'INCCAT'
FROM SQLDATA.dbo.CMLEDG
INNER JOIN SQLDATA.dbo.LEAS ON SQLDATA.dbo.CMLEDG.BLDGID = SQLDATA.dbo.LEAS.BLDGID
    AND SQLDATA.dbo.CMLEDG.LEASID = SQLDATA.dbo.LEAS.LEASID
INNER JOIN SQLDATA.dbo.RTBILL ON SQLDATA.dbo.CMLEDG.BLDGID = SQLDATA.dbo.RTBILL.BLDGID
    AND SQLDATA.dbo.CMLEDG.LEASID = SQLDATA.dbo.RTBILL.LEASID
INNER JOIN SQLDATA.dbo.BRKP ON SQLDATA.dbo.CMLEDG.BLDGID = SQLDATA.dbo.BRKP.BLDGID
    AND SQLDATA.dbo.CMLEDG.LEASID = SQLDATA.dbo.BRKP.LEASID
INNER JOIN SQLDATA.dbo.BRKP BRKP2 ON SQLDATA.dbo.CMLEDG.BLDGID = BRKP2.BLDGID
    AND SQLDATA.dbo.CMLEDG.LEASID = BRKP2.LEASID SQLDATA.DBO.BRKP.STARTDT = 
        (
            SELECT MAX(SQLDATA.DBO.BRKP.STARTDT)
            FROM SQLDATA.DBO.BRKP
            WHERE SQLDATA.DBO.LEAS.BLDGID = SQLDATA.DBO.BRKP.BLDGID
                AND SQLDATA.DBO.LEAS.LEASID = SQLDATA.DBO.BRKP.LEASID
        )
GROUP BY SQLDATA.dbo.BRKP.BLDGID,
    SQLDATA.dbo.BRKP.LEASID,
    SQLDATA.dbo.BRKP.STARTDT,
    SQLDATA.dbo.BRKP.BRKPNT1,
    SQLDATA.dbo.LEAS.OCCPSTAT,
    SQLDATA.dbo.LEAS.SUITID,
    SQLDATA.dbo.RTBILL.INCCAT
HAVING SQLDATA.dbo.BRKP.BLDGID & SPARM03
    AND SQLDATA.dbo.BRKP.STARTDT < Convert(datetime, '2016-08-31' )
    AND SQLDATA.dbo.LEAS.OCCPSTAT = 'c'

答案 2 :(得分:0)

目前还不清楚完全你需要什么。但是,显然您需要一个where子句并简化GROUP BY。因此,您的查询需要以下内容:

SELECT . . .,
       MAX(SQLDATA.dbo.BRKP.STARTDT)
FROM . . .
WHERE SQLDATA.dbo.BRKP.STARTDT < '20160831'
GROUP BY SQLDATA.dbo.BRKP.BLDGID,
    SQLDATA.dbo.BRKP.LEASID,
    SQLDATA.dbo.BRKP.BRKPNT1,
    SQLDATA.dbo.LEAS.OCCPSTAT,
    SQLDATA.dbo.LEAS.SUITID,
    SQLDATA.dbo.RTBILL.INCCAT
HAVING ( (SQLDATA.dbo.BRKP.STARTDT) < '20160831') AND 
         ((SQLDATA.dbo.LEAS.OCCPSTAT) = 'c')
        )

目前还不清楚是否有任何其他条件也应该移动WHERE条款,但我猜是“是”。

答案 3 :(得分:0)

请原谅我没有通过并将这一切都挂到您的代码中,但我理解您正在寻找的是

SELECT TOP (1)

然后

WHERE myDate <= @theDateValue

非常重要

ORDER BY myDate DESC

一般来说,这是你可以在某事之前得到最后一条记录的方法。上述示例中的性能会受到“myDate”上是否存在索引的影响很大,因为如果是这样,引擎可以直接转到正确的页面,只需读取一些内容并提取所需的单个记录。

答案 4 :(得分:0)

经常当有人想要与&#34;最大日期&#34;相关的数据时最好的方法是使用ROW_NUMBER()OVER()

我认为这可能会产生你想要的东西:

SELECT
        BLDGID
      , LEASID
      , STARTDT
      , BRKPNT1
      , OCCPSTAT
      , SUITID
      , INCCAT
FROM (
        SELECT
                br.BLDGID
              , br.LEASID
              , br.STARTDT
              , br.BRKPNT1
              , le.OCCPSTAT
              , le.SUITID
              , rb.INCCAT
              , ROW_NUMBER() OVER(PARTITION BY br.BLDGID, br.LEASID, le.OCCPSTAT, le.SUITID, rb.INCCAT
                                  ORDER BY br.STARTDT DESC) AS rowno
        FROM SQLDATA.dbo.CMLEDG cm
        INNER JOIN SQLDATA.dbo.LEAS le   ON cm.BLDGID = le.BLDGID AND cm.LEASID = le.LEASID
        INNER JOIN SQLDATA.dbo.RTBILL rb ON cm.BLDGID = rb.BLDGID AND cm.LEASID = rb.LEASID
        INNER JOIN SQLDATA.dbo.BRKP br   ON cm.BLDGID = br.BLDGID AND cm.LEASID = br.LEASID
        WHERE br.STARTDT < '20160831'
        AND le.OCCPSTAT = 'c'
     ) AS d
 WHERE rowno = 1

在OVER()内为&#34;分区列出的列&#34;行为有点像你的&#34;组&#34;因为当值组合发生变化时,重新开始计数。所以,因为这也是使用降序&#34;顺序&#34;对于&#34;最新日期&#34;,您希望日期得到值1。如果还与where子句结合使用:&lt; 20160831&#39;

之前的最近日期

我想提出几点补充说明:

  1. 问题中提供的查询存在语法错误,此处缺少AND&#34; = BRKP2.LEASID AND SQLDATA.DBO.BRKP.STARTDT&#34;
  2. 我不会这样做:&#34;有SQLDATA.dbo.BRKP.BLDGID &amp; SPARM03
  3. 如果提供别名的列不使用单引号,请使用[]或&#34;&#34; (即我建议您仅为文字保留使用单引号)。但是,也没有必要在此查询中提供列别名,因为您实际上并未实际更改列名称。
  4. 使用表别名有助于使查询更易于阅读
  5. 没有明显的理由使用GROUP BY,因为没有使用聚合函数
  6. HAVING子句用于过滤仅在组之后存在的聚合值。此查询中没有聚合值,因此不应该有having子句。 (a having子句不能替代where子句。)
  7. 没有理由我找到两次加入SQLDATA.dbo.BRKP