简体   繁体   English

如何使用 select、最大日期并在 sql 查询中声明?

[英]How to use select, max date and declare in a sql query?

I am trying to use declare and max in variable.我正在尝试在变量中使用声明和最大值。 This is the query below:这是下面的查询:

Declare @MAX_BUF Datetime
 
Set @OpeningStock = (
                    SELECT @MAX_BUF = MAX(end_date) FROM [IBIS].[buf_stk]
                    WHERE SUBSTRING(CONVERT(VARCHAR,end_date ,112 ),1,6)<SUBSTRING(CONVERT(VARCHAR,getdate() ,112 ),1,6);
                    
                    SELECT COUNT(1) AS Opening_Stock 
                    FROM [IBIS].[buf_stk] AS bs(NOLOCK)
                    WHERE CAST(end_date AS DATE)=@MAX_BUF
                    )

I am getting syntax error in '=' and '(end_date)'.我在 '=' 和 '(end_date)' 中遇到语法错误。 Please let me know if this can be resolved.请让我知道这是否可以解决。

Without seeing your table and data I can't be confident in rewriting your SQL correctly, however all you need to do to "make it work", I suspect, is amend slightly to:在没有看到您的表格和数据的情况下,我无法有信心正确地重写您的 SQL,但是我怀疑您需要做的就是“让它工作”,稍微修改为:

SELECT @MAX_BUF = MAX(end_date) FROM [IBIS].[buf_stk]
                    WHERE SUBSTRING(CONVERT(VARCHAR,end_date ,112 ),1,6)<SUBSTRING(CONVERT(VARCHAR,getdate() ,112 ),1,6);
                    
                    SELECT @OpeningStock=COUNT(*)
                    FROM [IBIS].[buf_stk] AS bs(NOLOCK) --<< Remove this!
                    WHERE CAST(end_date AS DATE)=@MAX_BUF

Having said that, you could combine these into a single query.话虽如此,您可以将这些组合成一个查询。 Your manipulation of dates as strings is not sargable and will force the optimizer to scan your table/index.您将日期作为字符串操作是不可分割的,并且会强制优化器扫描您的表/索引。

If you want to find rows where end_date is prior to 1st day of the month then just compare as dates (assuming your end_date is an actual date data type)如果您想查找end_date在该月的第一天之前的行,那么只需比较日期(假设您的end_date是实际的date数据类型)

where end_date < DATEADD(month, DATEDIFF(month, 0, GetDate()), 0)

And lose the nolock hint, unless you prefer your data to be randomly incorrect.并丢失nolock提示,除非您希望您的数据随机不正确。

Use two statements.使用两个语句。 I'm not a fan of converting dates to strings for date arithmetic.我不喜欢将日期转换为字符串以进行日期运算。 You seem to want the maximum date from before this month.您似乎想要本月之前的最大日期。 So, DATEDIFF() provides one method (and there are more efficient methods if you have an index on end_date ):因此, DATEDIFF()提供了一种方法(如果您在end_date上有索引,还有更有效的方法):

Set @@MAX_BUF = (SELECT CAST(MAX(end_date) as date)
                 FROM [IBIS].[buf_stk]
                 WHERE DATEDIFF(month, end_date, getdate()) >= 1
                );

Set @OpeningStock = (SELECT COUNT(1) AS Opening_Stock 
                     FROM [IBIS].[buf_stk] bs
                     WHERE CAST(end_date AS DATE) = @MAX_BUF
                    );

You can also do this as a single statement:您也可以将其作为单个语句执行:

select top (1)
       @max_buf = CAST(end_date as date),
       @OpeningStock = COUNT(*)
from FROM [IBIS].[buf_stk] bs
where end_date < dateadd(day, 1 - day(getdate()), convert(date, getdate()))
group by CAST(end_date as date)
order by CAST(end_date as date) desc;

Note that this also changes the date comparison to be friendlier to the optimizer.请注意,这也会将日期比较更改为对优化器更友好。

You can actually do this all in one statement and one scan of the table:实际上,您可以在一条语句和一次表扫描中完成所有操作:

SELECT @MAX_BUF = MAX(end_date), @OpeningStock = COUNT(1)
FROM
    (SELECT TOP (1) WITH TIES
        CAST(end_date AS date) end_date
    FROM [IBIS].[buf_stk]
    WHERE end_date >= DATEADD(month, 1, getdate())
    ORDER BY CAST(end_date AS date) DESC
    ) t;

Notes:笔记:

  • Don't use NOLOCK , it has many unintended effects and can cause incorrect results不要使用NOLOCK ,它有许多意想不到的效果,并可能导致不正确的结果
  • Switch round the WHERE predicate in order to hit an index if you have one.切换WHERE谓词以命中索引(如果有的话)。 Don't make the server do algebra for you, it's not very good at it.不要让服务器为你做代数,它不是很擅长。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM