【问题标题】:SQL case statement in a View logic视图逻辑中的 SQL 案例语句
【发布时间】:2021-09-13 17:54:25
【问题描述】:
CREATE VIEW [Myview] AS
SELECT 
  CASE
    WHEN 
    DATENAME(dw,DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0))='Sunday'
    THEN
        SELECT 
            cast(DATEPART(yyyy, getdate()-7) as varchar(4)) as YEAR,
            RIGHT('00'+cast(DATEPART(ww, getdate()-7) as varchar(2)),2) as WEEK;    
    ELSE
        SELECT 
            cast(DATEPART(yyyy, getdate()-14) as varchar(4)) as YEAR,
            RIGHT('00'+cast(DATEPART(ww, getdate()-14) as varchar(2)),2) as WEEK;
GO

创建时出错:Msg 103010, Level 16, State 1, Line 1 Parse 第 8 行错误,第 3 列:'SELECT' 附近的语法不正确。

帮我解决这个错误。 我想检查一年中的第一天是否是星期日,然后我会遵循 then 语句。然后语句建议获取周id和年份。enter image description here

【问题讨论】:

  • 请提供示例数据、所需结果以及您要实现的逻辑的说明。你的代码至少不能帮助我理解你想要做什么。
  • VIEW 的定义中有 2 个SELECT,但后者在CASE 表达式 内部。您还有 2 个语句(CASE 中间有语句终止符 (;),但 VIEW 是一个伪表,其定义由 single 语句定义。另外,需要强调的是,CASE 是一个表达式,而不是一个语句;它返回一个有效的标量,您正在尝试在其中定义 2 列。快速阅读CASE 表达式 documentation 会告诉你你的语法有多么错误。
  • 事实上,上面的内容甚至不应该是VIEW。它不会从任何表中返回数据。我怀疑,最好写成 inline 表值函数。
  • 没有 FROM 子句?!?
  • 所以当我使用以下查询时: cast(DATEPART(yyyy, getdate()-7) as varchar(4)) as YEAR, RIGHT('00'+cast(DATEPART(ww, getdate ()-7) as varchar(2)),2) as WEEK 它为我提供了当前年份和当前周的表格输出。但是我想实现这个条件: DATENAME(dw,DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0))='Sunday'

标签: sql sql-server ssms ssms-2014


【解决方案1】:

您的 SQL 存在多个问题。首先,您的查询中有 3 个 SELECT 语句;其中 2 个在您的 CASE Expression 中。 VIEW 是一个伪表,其定义由以SELECT 结尾的single 语句定义。您在这里有 2/3 语句,因此它不是 VIEW 的有效定义。

接下来,正如我所强调的,CASE 是 T-SQL 中的表达式不是语句。 T-SQL支持Case (Switch) 语句,仅支持CASE 表达式。 CASE 表达式返回一个标量值;不是语句,不是布尔结果。这意味着您只能从表达式中返回 一个 原子值,因此每个表达式 WHENELSE 也必须产生一个标量值。

但是,看看您在这里尝试过的内容,我什至不确定它是否属于 VIEW。它不引用任何表,通常是VIEW。我个人建议将其作为内联表值函数更好,它(如果我理解您的尝试正确的话)看起来像这样:

CREATE FUNCTION dbo.YourFunction()
RETURNS TABLE
AS RETURN
    SELECT CASE V.DayName WHEN 'Sunday' THEN DATEPART(YEAR, DATEADD(DAY, -7,GETDATE())) --I suggest leaving this as a strongly typed int
                          ELSE DATEPART(YEAR, DATEADD(DAY, -7,GETDATE())) --I suggest leaving this as a strongly typed int
           END AS [Year],
           CASE V.DayName WHEN 'Sunday' THEN DATEPART(WEEK, DATEADD(DAY, -7,GETDATE())) --I suggest leaving this as a strongly typed int
                          ELSE DATEPART(WEEK, DATEADD(DAY, -7,GETDATE()))
           END AS [Week]
    FROM (VALUES(DATENAME(WEEKDAY,DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()), 0))))V(DayName);
GO

我还整理了一些 SQL> 例如,我对日期部分始终使用相同的关键字,例如 YEARWEEK(您同时使用了 yyyyyy 表示年份),并替换将日期视为具有显式 DATEADD 逻辑的 int 的逻辑,因为它适用于 any 日期和时间数据类型(不仅仅是旧的 (small)datetime 数据类型)。

然后你会像这样调用函数:

--On it's own
SELECT [Year], [Week]
FROM dbo.YourFunction();

--When using other tables
SELECT {Some Columns}
FROM dbo.YourTable YT
     CROSS APPLY dbo.YourFunction() YF;

【讨论】:

    猜你喜欢
    • 2016-09-08
    • 2016-10-01
    • 1970-01-01
    • 2013-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-22
    相关资源
    最近更新 更多