0

I need to make a case statement.

Depending on what the variables value is, it needs to select the correct column from the table

StartDate and EndDate are different variables.

There is a variable i created called Region which should determine what column the query selects.

EDIT: Region can either be 'EW' for England and Wales, 'SC' for Scotland or 'NI' for Northern Ireland. If it is EW it should select column 1, SC for column 2, NI for column 3

SELECT
COUNT(COLUMN1)
FROM  bankholidays
WHERE COLUMN1 BETWEEN @StartDate AND @EndDate)
  • That means, you want to select column dynamically ? – Shushil Bohara Dec 20 '16 at 11:05
  • 1
    Kindly provide sample data and expected data – Viki888 Dec 20 '16 at 11:08
  • 1
    Does the column you count on matter; i.e. are there null values you're concerned about, or would `count(*)` or `count(1)` (functionally identical) be OK? Alternatively, is it the column in your WHERE statement that you're interested in? – JohnLBevan Dec 20 '16 at 11:17

6 Answers6

2

Assuming you want to count the number of records for which Column1 is in between the start and end date, then the following should work:

SELECT SUM(CASE WHEN COLUMN1 BETWEEN @StartDate AND @EndDate
           THEN 1 ELSE 0 END) AS tally
FROM bankholidays

This approach is called conditional aggregation, and often you will also use a GROUP BY clause.

Update:

To handle your @Region variable, a query might look like this:

SELECT CASE WHEN @Region = 'val1' THEN COLUMN1
            WHEN @Region = 'val2' THEN COLUMN2
            WHEN @Region = 'val3' THEN COLUMN3
       END AS new_column   
FROM bankholidays

Note that I did not attempt to combine this with the first query because it would mix aggregate functions with non aggregate terms, and it might not make sense.

Tim Biegeleisen
  • 502,043
  • 27
  • 286
  • 360
  • My other variable is @Region, it can contain 3 different values. How do i use this to choose column 1, column 2 or column 3? –  Dec 20 '16 at 11:22
1

1) If you're not concerned about excluding nulls from your count, you don't need to specify a column name in your COUNT statement. i.e.

select count(Column1)

Will give the same result as

select count(1)

Or

select count(*)

So long as column1 has no null values. If column1 does contain nulls, those aren't counted (so if there are 10 records, 3 of which have null values in column1, you'd get a result of 7 using count(column1) or a count of 10 using the other methods.

I mention this first as if you care about nulls then changing which column is used here makes sense; if you don't, go with the simpler logic of just count(1) / counnt(*).

All that said, here's how to change that column:

select count(
    case @Region 
        when 1 then Column1 
        when 2 then Column2 
        else Column3 
    end
)

2) If you want to change the column used in your WHERE statement, there are a couple of approaches:

SELECT COUNT(1)
FROM  bankholidays
WHERE case @Region 
    when 1 then Column1 
    when 2 then Column2 
    else Column3        
end BETWEEN @StartDate AND @EndDate

or

SELECT COUNT(1)
FROM  bankholidays
WHERE (@Region = 1 and Column1 BETWEEN @StartDate AND @EndDate)
or (@Region = 2 and Column2 BETWEEN @StartDate AND @EndDate
or (@Region not in (1,2) and Column3 BETWEEN @StartDate AND @EndDate

Personally I prefer the first style above, since it involves less repetition; however the second style offers the option to use different start & end dates for the different columns, or to add in other logic too, so is still worth being aware of.

JohnLBevan
  • 22,735
  • 13
  • 96
  • 178
  • If you're interested in the `count(1)` vs `count(*)` piece, there's discussions on that here: http://stackoverflow.com/questions/1221559/count-vs-count1. `Count(*)` is more commonly recognisedm but I prefer `count(1)` as I feel it's more meaningful, and is also more in line with other aggregate operators (e.g. `sum(1)`) – JohnLBevan Dec 20 '16 at 11:31
1
SELECT CASE
WHEN @Region = 'EW' THEN columnName
WHEN @Region = 'SC' THEN columnName
WHEN @Region = 'NI' THEN columnName
END AS newColumnName FROM bankholidaysT

Try something like this

someguy76
  • 415
  • 4
  • 22
0

If you want to dynamically count records where a given column value is between two dates, use a dynamic query:

DECLARE @column NVARCHAR(MAX)
DECLARE @sql NVARCHAR(MAX)

SET @column = 'COLUMN1' --Set your desired column here
SET @sql = 'SELECT COUNT(*) FROM bankholidays WHERE ' + @column + ' BETWEEN ''' + CONVERT(NVARCHAR,@StartDate,121) + ''' AND ''' + CONVERT(NVARCHAR,@EndDate,121) + ''''

EXEC @sql
3N1GM4
  • 3,372
  • 3
  • 19
  • 40
  • I'd only ever advise dynamic sql as a last resort, especially if writing it as a stored procedure or query that might be maintained in the future. For one offs its not so bad. – Charleh Dec 20 '16 at 11:16
  • I'm not saying you're wrong, but out of interest - why? – 3N1GM4 Dec 20 '16 at 11:19
  • Because it's hard to maintain, especially when the query grows over time. I've had some nightmares with dynamic SQL that didn't need to be there. You also don't get intellisense which helps when you have long object names or can't remember which parameter goes where in a function. Who wants to spend 15-20 minutes unraveling sometimes dynamic mess just to change the join a little? If you can do it without, do it without. Leave dynamic SQL building to the ORMs or use synonyms or just ...something. – Charleh Dec 21 '16 at 11:33
0

TRY THIS IF you want to count and check the column dynamically

DECLARE @sql VARCHAR(500), 
    @Region VARCHAR(100) = 'COLUMN2', --It can be Column1, Column2.....
    @StartDate DATETIME = '2016-04-10',
    @EndDate DATETIME = '2016-04-15'

SET @sql = '
    SELECT
    COUNT(' + @Region + ')
    FROM  bankholidays
    WHERE ' + @Region + ' BETWEEN ''' + CAST(@StartDate AS VARCHAR) + ''' AND ''' + CAST(@EndDate AS VARCHAR) + ''''

EXEC (@SQL)

--Query executed as below

SELECT
COUNT(COLUMN2)--It can be Column1, Column2.....
FROM  bankholidays
WHERE COLUMN2 BETWEEN 'Apr 10 2016 12:00AM' AND 'Apr 15 2016 12:00AM'
Shushil Bohara
  • 5,556
  • 2
  • 15
  • 32
-1
declare  @Region  varchar(10)
set @Region='EW'

SELECT 
COUNT(*) OVER(PARTITION BY 1) as TotalRows,
Case  
    when @Region ='EW' THEN   Column1 
    when @Region ='SC' THEN   Column2
    when @Region ='NI' THEN   Column3
end as [NewColumn]
FROM [BankHolidays] 
WHERE COLUMN1 BETWEEN @StartDate AND @EndDate
Prasanth V J
  • 1,126
  • 14
  • 32
  • I think the question also requires the column in the `WHERE` clause to also be dynamically specified depending on the value of `@Region`. – 3N1GM4 Dec 21 '16 at 11:40