Reputation: 31
Table structure like this
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
I want select users that have column value 1 of specific timecolumn I have used following query but it is throwing error
com.microsoft.sqlserver.jdbc.SQLServerException: Conversion failed when converting the varchar value '[ 3PM]' to data type 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
Like this when I use hardcoded column name then it works fine I want to select a column name dynamically.
select * from UserDetail u,TimeTable t
where u.userid = t.userid
and [3AM] = 1
Upvotes: 0
Views: 2720
Reputation: 400
Option 1
Use a long list of short-circuited WHERE clauses like below which seems fine given the table design and quite easy to understand
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
Option 2
Use UNPIVOT or VALUES to rotate the hour based columns into rows. As part of the rotate you can translate the column into a number indicating the hour. This you can compare with the current time’s hour component.
Option 3
Use dynamic sql which might or might not be ok for your environment or usage.
Below is the UNPIVOT approach (Option 2) which is a bit more complex to understand.
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
Intermediate output from MatchingIds for above example with time param set to around 1am
| id |
|----|
| 1 |
| 3 |
http://sqlfiddle.com/#!18/85c9c/5
Upvotes: 1
Reputation: 4994
select CONCAT(SUBSTRING(CONVERT(VARCHAR, getdate(), 100), 13, 2) ,'',RIGHT(CONVERT(VARCHAR, GETDATE(), 100),2))
is a value of type varchar
, not the syntax of a query. What you are currently doing is for sql similar to:
select * from UserDetail u,TimeTable t
where u.userid=t.userid
and '12PM' = 1
Even if parser accepted your query the condition would always be false as '12PM'
is not the same as 12PM
or [12PM]
. You cannot dynamically modify a query within the query itself to make it work.
Yes, you could do tricks like dynamic execution (build entire query as string and then execute it), but please -don't. The real problem in you code is that you have a rather bad table design. Consider redesigning your TimeTable
table to have timeOfDay values a single column and actual time values as data in that column. You'll save yourself a lot of headache later.
Upvotes: 0
Reputation: 1731
Try:
select * from UserDetail u,TimeTable t
where u.userid=t.userid
and
(select COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = 'tblName'
AND TABLE_CATALOG = 'DBNAME'
AND COLUMN_NAME = CONCAT(SUBSTRING(CONVERT(VARCHAR, getdate(), 100), 13, 2) ,'',RIGHT(CONVERT(VARCHAR, GETDATE(), 100),2))) = 1
Upvotes: 0