【问题标题】:Stuck with SQL statement again. Error: "Invalid column name"再次卡住 SQL 语句。错误:“列名无效”
【发布时间】:2011-07-16 04:24:03
【问题描述】:

我正在尝试使以下 SQL 服务器语句工作,但我收到此错误:“无效的列名 'bfg'。”

WITH valDiff AS (
 SELECT 

  CASE 
   WHEN DATEADD(second, 604800, [InTime]) <= [OutTime] THEN [OutTime]
   ELSE DATEADD(second, 604800, [InTime]) 
  END AS bfg,

 datediff(second,
  CASE 
   WHEN [InTime] >= @in THEN [InTime]
   ELSE @in 
  END,
  CASE  
   WHEN bfg <= @out THEN bfg  
  ELSE @out 
 END) 

 AS v1 FROM [MyTable] 

 WHERE 
 AND [InTime] <= @out 
 AND  bfg >= @in

) SELECT SUM(v1) FROM valDiff;

简而言之,第一个带有 DATEADD 的 CASE 应该将 'bfg' 设置为 min(OutTime, InTime + 7 days)。第二部分或 DATEDIFF 应计算 InTime 字段和上面计算的 'bfg' 之间的时间差(以秒为单位),如果它们在 @in 和 @out 时间范围内。

我希望我更了解 SQL ......你如何解决它?

【问题讨论】:

    标签: sql sql-server case datediff dateadd


    【解决方案1】:

    在同一查询中创建别名 bfg 后,您不能使用它。这样做的强烈需要通常表示需要将代码放入 JOIN 子句中,以便您可以从别名中引用它。

    INNER JOIN 解决方案

    这是“漂亮”选项。再次加入你的餐桌。

    SELECT 
      T2.bfg,
      datediff(second,
        CASE WHEN [InTime] >= @in THEN [InTime] ELSE @in END,
        CASE WHEN T2.bfg <= @out THEN T2.bfg ELSE @out END) 
      AS v1 
    FROM 
      [MyTable] as T1
      inner join
      ( SELECT MyTableID,
         CASE 
          WHEN DATEADD(second, 604800, [InTime]) <= [OutTime] THEN [OutTime]
          ELSE DATEADD(second, 604800, [InTime]) 
         END AS bfg
        FROM
         [MyTable]
      ) as T2 on T2.MyTableID = T1.MyTableID 
    WHERE 
      [InTime] <= @out 
      AND  T2.bfg >= @in
    


    查看方法

    您可以创建一个视图,然后从中选择。

    执行一次:

    CREATE VIEW MyView as
    SELECT
     CASE 
       WHEN DATEADD(second, 604800, [InTime]) <= [OutTime] THEN [OutTime]
       ELSE DATEADD(second, 604800, [InTime]) 
      END AS bfg,
     *
    FROM
     [MyTable]
    

    然后,您的查询将如下所示:

    WITH valDiff AS (
     SELECT 
      bfg,
      datediff(second,
       CASE 
        WHEN [InTime] >= @in THEN [InTime]
        ELSE @in 
       END,
       CASE  
        WHEN bfg <= @out THEN bfg  
       ELSE @out 
      END) AS v1 
    FROM [MyView] 
    WHERE 
     [InTime] <= @out 
     AND  bfg >= @in
    ) SELECT SUM(v1) FROM valDiff;
    


    丑陋的解决方案

    这只是将您的案例声明复制粘贴到 3 个位置的问题。

    您必须将 WHERE 子句(和其他位置)中的 bfg 替换为以下内容:

    CASE 
     WHEN DATEADD(second, 604800, [InTime]) <= [OutTime] THEN [OutTime]
     ELSE DATEADD(second, 604800, [InTime]) 
    END
    

    因此您的整个代码如下:

    WITH valDiff AS (
     SELECT 
    
      CASE 
       WHEN DATEADD(second, 604800, [InTime]) <= [OutTime] THEN [OutTime]
       ELSE DATEADD(second, 604800, [InTime]) 
      END AS bfg,
    
     datediff(second,
      CASE 
       WHEN [InTime] >= @in THEN [InTime]
       ELSE @in 
      END,
      CASE  
       WHEN 
         CASE WHEN DATEADD(second, 604800, [InTime]) <= [OutTime] THEN [OutTime]
         ELSE DATEADD(second, 604800, [InTime]) 
         END 
       <= @out THEN 
         CASE 
         WHEN DATEADD(second, 604800, [InTime]) <= [OutTime] THEN [OutTime]
         ELSE DATEADD(second, 604800, [InTime]) 
         END
      ELSE @out 
     END) 
    
     AS v1 FROM [MyTable] 
    
     WHERE 
     [InTime] <= @out 
     AND  CASE 
       WHEN DATEADD(second, 604800, [InTime]) <= [OutTime] THEN [OutTime]
       ELSE DATEADD(second, 604800, [InTime]) 
      END >= @in
    
    ) SELECT SUM(v1) FROM valDiff;
    

    【讨论】:

    • 但是没有办法将带有 'bfg' 的 CASE 检查移出,是吗?我只是想提高效率....
    • 哇,谢谢老兄!让我测试一下,然后我会将其标记为答案。非常感谢....为什么我不知道这样的 SQL :)
    • 另一个有效的选项是创建一个view,它将包含该 BFG 值作为列,然后您可以使用此查询从视图中进行选择,而无需任何 JOIN 或讨厌的 bfg-case 语句
    • 很抱歉,您是如何制作视图的?
    • 我可能错了,但我认为inner join 的版本可能是最快的;但是,它可能与视图相同。话虽如此,您可以考虑提出另一个问题,即是否真的有必要做其中的 90 个陈述。可能有更好的方法。祝你好运
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-07
    • 2011-01-21
    • 2021-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多