如何在where子句sql中使用函数结果作为列名

时间:2018-04-04 10:50:18

标签: sql-server

像这样的表结构

select * from TimeTable;

        userid | 1am|2am|3am| 4am| 5am
        1002   | 1  |1  |1  | 1  | 1
        1003   | 1  |1  |1  | 1  | 1 
        1004   | 1  |1  |1  | 1  | 1
        1005   | 1  |1  |1  | 1  | 1

我希望选择具有特定时间列的列值1的用户 我使用了以下查询,但它正在抛出错误

  

com.microsoft.sqlserver.jdbc.SQLServerException:转换失败   将varchar值'[3PM]'转换为数据类型int。

select * from UserDetail u,TimeTable t  
where u.userid=t.userid
and CONCAT(SUBSTRING(CONVERT(VARCHAR, getdate(), 100), 13, 2) ,'',RIGHT(CONVERT(VARCHAR, GETDATE(), 100),2)) = 1

喜欢这个 当我使用硬编码列名称时,它工作正常 我想动态选择一个列名。

select * from UserDetail u,TimeTable t  
where u.userid = t.userid
and [3AM] = 1

3 个答案:

答案 0 :(得分:0)

选项1

使用下面列出的短路WHERE子句列表,看起来很好,因为桌面设计很容易理解

DECLARE @currentHour int = DATEPART(HOUR, getdate())
SELECT * FROM TimeTable
WHERE
    (@currentHour = 1 AND [1am] = 1) OR
    (@currentHour = 2 AND [2am] = 1) OR
    (@currentHour = 3 AND [3am] = 1) OR
    (@currentHour = 4 AND [4am] = 1) OR
    (@currentHour = 5 AND [5am] = 1) -- Etc

选项2

使用UNPIVOT或VALUES将基于小时的列旋转为行。作为旋转的一部分,您可以将列转换为表示小时的数字。这可以与当前时间的小时组件进行比较。

选项3

使用动态sql,它可能适合您的环境或使用,也可能不适用。

以下是UNPIVOT方法(选项2),理解起来有点复杂。

create table Test (id int, [1am] int, [2am] int, [3am] int, [4am] int)

insert Test values
  (1, 1, 2, 3, 4)
  , (2, 11, 12, 13, 14)
  , (3, 1, 21, 23, 24)
  , (4, 31, 32, 33, 34)

declare @time datetime = '2018-01-01 01:10:00' -- change this to getdate()

;WITH MatchingIds (id) AS
(
  SELECT id
  FROM
    (SELECT 
       id,  
       [1am] AS [1], [2am] AS [2], [3am] AS [3], [4am] AS [4] --etc 
     FROM Test) AS Source
     UNPIVOT
     (val FOR hour IN 
      ([1], [2], [3], [4]) --etc
     ) AS asRows
  WHERE 
      hour = CONVERT(VARCHAR, DATEPART(HOUR, @time)) 
      AND val = 1
) 
SELECT * FROM MatchingIds
-- MatchingIds now contains the rows that match your criteris
-- This can be joined with other tables to generate your full result

以上示例的MatchingIds的中间输出,时间参数设置为凌晨1点左右

| id |
|----|
|  1 |
|  3 |

http://sqlfiddle.com/#!18/85c9c/5

答案 1 :(得分:0)

尝试:

<div class="flex-grid">
  			  <div class="col"><img src="https://cdn.shopify.com/s/files/1/2503/1376/files/artificial.jpg?3140817636037500562"></div>
              <div class="col"><img src="https://cdn.shopify.com/s/files/1/2503/1376/files/artificial.jpg?3140817636037500562"></div>
              <div class="col"><img src="https://cdn.shopify.com/s/files/1/2503/1376/files/artificial.jpg?3140817636037500562"></div>
              <div class="col"><img src="https://cdn.shopify.com/s/files/1/2503/1376/files/artificial.jpg?3140817636037500562"></div>
              <div class="col"><img src="https://cdn.shopify.com/s/files/1/2503/1376/files/artificial.jpg?3140817636037500562"></div>
              <div class="col"><img src="https://cdn.shopify.com/s/files/1/2503/1376/files/artificial.jpg?3140817636037500562"></div>
              <div class="col"><img src="https://cdn.shopify.com/s/files/1/2503/1376/files/artificial.jpg?3140817636037500562"></div>
              <div class="col"><img src="https://cdn.shopify.com/s/files/1/2503/1376/files/artificial.jpg?3140817636037500562"></div>
			</div>

答案 2 :(得分:0)

select CONCAT(SUBSTRING(CONVERT(VARCHAR, getdate(), 100), 13, 2) ,'',RIGHT(CONVERT(VARCHAR, GETDATE(), 100),2))varchar类型的值,而不是查询的语法。您目前正在做的是sql类似于:

select * from UserDetail u,TimeTable t  
where u.userid=t.userid
and '12PM' = 1

即使解析器接受了您的查询,但条件始终为false,因为'12PM'12PM[12PM]不同。您无法在查询本身内动态修改查询以使其正常工作。

是的,你可以做动态执行的技巧(将整个查询构建为字符串,然后执行它),但请不要。您的代码中的真正问题是您的表格设计相当糟糕。考虑重新设计TimeTable表,使timeOfDay值为单列,将实际时间值作为该列中的数据。你以后会为自己省下很多头痛。