SQL Server Subquery Return Error - sql

When I try to execute my statements, I get an error that returns "Subquery returned more than 1 value. Not allowed...," you know the rest. I'm not good with subqueries, in fact it's guessing with trial and error sometimes until I see the result I'm trying to gather. Can anyone explain to me the issue of why it's returning with this error?
I'm trying to return the score for one person's game before moving on to return all players from the same game.
The file is here if the data is relevant: SQL File
SELECT
TP.intPlayerID
,TP.strLastName + ', ' + TP.strFirstName AS strPlayerName
,TG.*
,TR.intGameID
,(
SELECT
CASE WHEN Game.F1S1 = 10 and Game.F2S1 = 10 THEN 20 + Game.F3S1
WHEN Game.F1S1 = 10 and Game.F2S1 < 10 THEN 10 + Game.F2S1 + Game.F2S2
WHEN Game.F1S1 + Game.F1S2 = 10 THEN 10 + Game.F2S1
ELSE Game.F1S1 + Game.F1S2
END
+
CASE WHEN Game.F2S1 = 10 and Game.F3S1 = 10 THEN 20 + Game.F4S1
WHEN Game.F2S1 = 10 and Game.F3S1 < 10 THEN 10 + Game.F3S1 + Game.F3S2
WHEN Game.F2S1 + Game.F2S2 = 10 THEN 10 + Game.F3S1
ELSE Game.F2S1 + Game.F2S2
END
+
CASE WHEN Game.F3S1 = 10 and Game.F4S1 = 10 THEN 20 + Game.F5S1
WHEN Game.F3S1 = 10 and Game.F4S1 < 10 THEN 10 + Game.F4S1 + Game.F4S2
WHEN Game.F3S1 + Game.F3S2 = 10 THEN 10 + Game.F4S1
ELSE Game.F3S1 + Game.F3S2
END
+
CASE WHEN Game.F4S1 = 10 and Game.F5S1 = 10 THEN 20 + Game.F6S1
WHEN Game.F4S1 = 10 and Game.F5S1 < 10 THEN 10 + Game.F5S1 + Game.F5S2
WHEN Game.F4S1 + Game.F4S2 = 10 THEN 10 + Game.F5S1
ELSE Game.F4S1 + Game.F4S2
END
+
CASE WHEN Game.F5S1 = 10 and Game.F6S1 = 10 THEN 20 + Game.F7S1
WHEN Game.F5S1 = 10 and Game.F6S1 < 10 THEN 10 + Game.F6S1 + Game.F6S2
WHEN Game.F5S1 + Game.F5S2 = 10 THEN 10 + Game.F6S1
ELSE Game.F5S1 + Game.F5S2
END
+
CASE WHEN Game.F6S1 = 10 and Game.F7S1 = 10 THEN 20 + Game.F8S1
WHEN Game.F6S1 = 10 and Game.F7S1 < 10 THEN 10 + Game.F7S1 + Game.F7S2
WHEN Game.F6S1 + Game.F6S2 = 10 THEN 10 + Game.F7S1
ELSE Game.F6S1 + Game.F6S2
END
+
CASE WHEN Game.F7S1 = 10 and Game.F8S1 = 10 THEN 20 + Game.F9S1
WHEN Game.F7S1 = 10 and Game.F8S1 < 10 THEN 10 + Game.F8S1 + Game.F8S2
WHEN Game.F7S1 + Game.F7S2 = 10 THEN 10 + Game.F8S1
ELSE Game.F7S1 + Game.F7S2
END
+
CASE WHEN Game.F8S1 = 10 and Game.F9S1 = 10 THEN 20 + Game.F10S1
WHEN Game.F8S1 = 10 and Game.F9S1 < 10 THEN 10 + Game.F9S1 + Game.F9S2
WHEN Game.F8S1 + Game.F8S2 = 10 THEN 10 + Game.F9S1
ELSE Game.F8S1 + Game.F8S2
END
+
CASE WHEN Game.F9S1 = 10 and Game.F10S1 = 10 THEN 20 + Game.F10S2
WHEN Game.F9S1 = 10 and Game.F10S1 < 10 THEN 10 + Game.F10S1 + Game.F10S2
WHEN Game.F9S1 + Game.F9S2 = 10 THEN 10 + Game.F10S1
ELSE Game.F9S1 + Game.F9S2
END
+
CASE WHEN Game.F10S1 = 10 and Game.F10S2 = 10 THEN 20 + Game.F10S3
WHEN Game.F10S1 = 10 and Game.F10S2 < 10 THEN 10 + Game.F10S2 + Game.F10S3
WHEN Game.F10S1 + Game.F10S2 = 10 THEN 10 + Game.F10S3
ELSE Game.F10S1 + Game.F10S2
END
AS GameScore
FROM
(
SELECT
TR.intGameID
,SUM( CASE WHEN TR.intRollIndex = 1 and TR.intRollNumberIndex = 1 THEN TR.intNumberOfPins ELSE 0 END ) F1S1
,SUM( CASE WHEN TR.intRollIndex = 1 and TR.intRollNumberIndex = 2 THEN TR.intNumberOfPins ELSE 0 END ) F1S2
,SUM( CASE WHEN TR.intRollIndex = 2 and TR.intRollNumberIndex = 1 THEN TR.intNumberOfPins ELSE 0 END ) F2S1
,SUM( CASE WHEN TR.intRollIndex = 2 and TR.intRollNumberIndex = 2 THEN TR.intNumberOfPins ELSE 0 END ) F2S2
,SUM( CASE WHEN TR.intRollIndex = 3 and TR.intRollNumberIndex = 1 THEN TR.intNumberOfPins ELSE 0 END ) F3S1
,SUM( CASE WHEN TR.intRollIndex = 3 and TR.intRollNumberIndex = 2 THEN TR.intNumberOfPins ELSE 0 END ) F3S2
,SUM( CASE WHEN TR.intRollIndex = 4 and TR.intRollNumberIndex = 1 THEN TR.intNumberOfPins ELSE 0 END ) F4S1
,SUM( CASE WHEN TR.intRollIndex = 4 and TR.intRollNumberIndex = 2 THEN TR.intNumberOfPins ELSE 0 END ) F4S2
,SUM( CASE WHEN TR.intRollIndex = 5 and TR.intRollNumberIndex = 1 THEN TR.intNumberOfPins ELSE 0 END ) F5S1
,SUM( CASE WHEN TR.intRollIndex = 5 and TR.intRollNumberIndex = 2 THEN TR.intNumberOfPins ELSE 0 END ) F5S2
,SUM( CASE WHEN TR.intRollIndex = 6 and TR.intRollNumberIndex = 1 THEN TR.intNumberOfPins ELSE 0 END ) F6S1
,SUM( CASE WHEN TR.intRollIndex = 6 and TR.intRollNumberIndex = 2 THEN TR.intNumberOfPins ELSE 0 END ) F6S2
,SUM( CASE WHEN TR.intRollIndex = 7 and TR.intRollNumberIndex = 1 THEN TR.intNumberOfPins ELSE 0 END ) F7S1
,SUM( CASE WHEN TR.intRollIndex = 7 and TR.intRollNumberIndex = 2 THEN TR.intNumberOfPins ELSE 0 END ) F7S2
,SUM( CASE WHEN TR.intRollIndex = 8 and TR.intRollNumberIndex = 1 THEN TR.intNumberOfPins ELSE 0 END ) F8S1
,SUM( CASE WHEN TR.intRollIndex = 8 and TR.intRollNumberIndex = 2 THEN TR.intNumberOfPins ELSE 0 END ) F8S2
,SUM( CASE WHEN TR.intRollIndex = 9 and TR.intRollNumberIndex = 1 THEN TR.intNumberOfPins ELSE 0 END ) F9S1
,SUM( CASE WHEN TR.intRollIndex = 9 and TR.intRollNumberIndex = 2 THEN TR.intNumberOfPins ELSE 0 END ) F9S2
,SUM( CASE WHEN TR.intRollIndex = 10 and TR.intRollNumberIndex = 1 THEN TR.intNumberOfPins ELSE 0 END ) F10S1
,SUM( CASE WHEN TR.intRollIndex = 10 and TR.intRollNumberIndex = 2 THEN TR.intNumberOfPins ELSE 0 END ) F10S2
,SUM( CASE WHEN TR.intRollIndex = 10 and TR.intRollNumberIndex = 3 THEN TR.intNumberOfPins ELSE 0 END ) F10S3
FROM
TRolls AS TR
GROUP BY
TR.intGameID ) AS Game )
FROM
TPlayers AS TP
,TGames AS TG
,TRolls AS TR
WHERE
TP.intPlayerID = TG.intPlayerID
AND TG.intGameID = TR.intGameID
AND TP.intPlayerID = 21

It's a bit difficult to debug without the table designs but from what I see in your query, there may be a few issues (again, depending on your table design).
Your inner subquery does not have a Where Statement. Therefore, it
will bring all games in TRolls table, grouped by intGameID; It will
return multiple games; this is probably the issue as the "Game"
subquery is used in a SELECT statement, so it should return only one row;
you may need to add a WHERE clause to your subquery, and
maybe another join, depending on your table structure and their
relationships. If you really need to get the score for each game
(meaning, you don't know the gameID yet) you need to do that in the
FROM statement (not in the select statement as you are) like this
SELECT
TP.intPlayerID
,TP.strLastName + ', ' + TP.strFirstName AS strPlayerName
,TG.*
,TR.intGameID
,Game.Gamescore
FROM
TPlayers AS TP
,TGames AS TG
,TRolls AS TR
, (Select ... ...
) As Game
WHERE ...
From your question I understand in a Game you have multiple Players.
You are filtering just "PlayerID = 21" so you are adding all the
scores from all games for that player - is that what you really want?
Or are you missing another condition to filter a specific game?
You mentioned you are not familiar with subqueries, so here's a quick rule of thumb:
If used in the Select Statement (like yours) a subquery can only
return one row. Always.
If used in the From Statement (like my example) it brings you a
virtual "temp table" with multiple rows, you enclose it in
parenthesis and use an Alias to identify it; then you join it with
other tables in your From Statement using its given Alias.
If used in the Where Statement it should return a boolean value (true
or false), and a common example of that would be verifying whether or
not an information exists somewhere, like this:
WHERE EXISTS (SELECT 'X' from .... Where ....)

Related

SQL Server : find members from a number

Problem : How to find out from the given number from which numbers this number consists?
"Sunday = 1", "Monday = 2", "Tuesday = 4", Wednesday = 8", "Thursday =
16", "Friday = 32", "Saturday = 64"
For example : Given the number 109 this would signify Sunday, Tuesday, Wednesday, Friday, Saturday
You can do something like this.
CREATE FUNCTION dbo.Int2BinaryToWeekDay (#i INT) RETURNS NVARCHAR(2048) AS BEGIN
RETURN
CASE WHEN CONVERT(VARCHAR(16), #i & 64 ) > 0 THEN 'Saturday,' ELSE '' END +
CASE WHEN CONVERT(VARCHAR(16), #i & 32 ) > 0 THEN 'Friday,' ELSE '' END +
CASE WHEN CONVERT(VARCHAR(16), #i & 16 ) > 0 THEN 'Thurday,' ELSE '' END +
CASE WHEN CONVERT(VARCHAR(16), #i & 8 ) > 0 THEN 'Wed,' ELSE '' END +
CASE WHEN CONVERT(VARCHAR(16), #i & 4 ) > 0 THEN 'Tuesday,' ELSE '' END +
CASE WHEN CONVERT(VARCHAR(16), #i & 2 ) > 0 THEN 'Monday,' ELSE '' END +
CASE WHEN CONVERT(VARCHAR(16), #i & 1 ) > 0 THEN 'Sunday,' ELSE '' END
END;
GO
Now do following thing.
SELECT dbo.Int2BinaryToWeekDay(109)
Looks like a binary design. You need to use bitwise & operator to get the desired output.
Decimal = Binary
109 = 1101101
001 = 0000001
------&------
0000001 = 1
109 = 1101101
002 = 0000010
------&------
0000000 = 0
109 = 1101101
004 = 0000100
------&------
0000100 = 4
SQL Server has bitwise operators in built. you can utilize bitwise & for this like:
DECLARE #InputNum INT = 109
SELECT ISNULL(STUFF(CASE WHEN #InputNum & 1 > 0 THEN ', SUN' ELSE '' END +
CASE WHEN #InputNum & 2 > 0 THEN ', MON' ELSE '' END +
CASE WHEN #InputNum & 4 > 0 THEN ', TUE' ELSE '' END +
CASE WHEN #InputNum & 8 > 0 THEN ', WED' ELSE '' END +
CASE WHEN #InputNum & 16 > 0 THEN ', THU' ELSE '' END +
CASE WHEN #InputNum & 32 > 0 THEN ', FRI' ELSE '' END +
CASE WHEN #InputNum & 64 > 0 THEN ', SAT' ELSE '' END,1,2,''),'')
check the MS documentation for more detailed explaination of bitwise operators.

SQL Query not producing 'Disabled' jobs within the results, alongside 'Failed' jobs

I have the following code for a SQL Query I'm working on..
DECLARE #Date datetime
SET #Date = DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))
DECLARE #jobHistory TABLE
(
job_id UNIQUEIDENTIFIER
, success INT
, cancel INT
, fail INT
, retry INT
, last_execution_id INT
, last_duration CHAR(8)
, last_execution_start DATETIME
);
WITH lastExecution
AS
(
SELECT job_id
, MAX(instance_id) AS last_instance_id
FROM msdb.dbo.sysjobhistory
WHERE step_id = 0
GROUP BY job_id
)
INSERT INTO #jobHistory
SELECT sjh.job_id
, SUM(CASE WHEN sjh.run_status = 1 AND step_id = 0 THEN 1 ELSE 0 END) AS success
, SUM(CASE WHEN sjh.run_status = 3 AND step_id = 0 THEN 1 ELSE 0 END) AS cancel
, SUM(CASE WHEN sjh.run_status = 0 AND step_id = 0 THEN 1 ELSE 0 END) AS fail
, SUM(CASE WHEN sjh.run_status = 2 THEN 1 ELSE 0 END) AS retry
, MAX(CASE WHEN sjh.step_id = 0 THEN instance_id ELSE NULL END) last_execution_id
, SUBSTRING(CAST(MAX(CASE WHEN le.job_id IS NOT NULL THEN sjh.run_duration ELSE NULL END) + 1000000 AS VARCHAR(7)),2,2) + ':'
+ SUBSTRING(CAST(MAX(CASE WHEN le.job_id IS NOT NULL THEN sjh.run_duration ELSE NULL END) + 1000000 AS VARCHAR(7)),4,2) + ':'
+ SUBSTRING(CAST(MAX(CASE WHEN le.job_id IS NOT NULL THEN sjh.run_duration ELSE NULL END) + 1000000 AS VARCHAR(7)),6,2)
AS last_duration
, MAX(CASE WHEN le.last_instance_id IS NOT NULL THEN
CONVERT(datetime, RTRIM(run_date))
+ ((run_time / 10000 * 3600)
+ ((run_time % 10000) / 100 * 60)
+ (run_time % 10000) % 100) / (86399.9964)
ELSE '1900-01-01' END) AS last_execution_start
FROM msdb.dbo.sysjobhistory AS sjh
LEFT JOIN lastExecution AS le
ON sjh.job_id = le.job_id
AND sjh.instance_id = le.last_instance_id
GROUP BY sjh.job_id;
DECLARE #weekDay TABLE (
mask INT
, maskValue VARCHAR(32)
);
INSERT INTO #weekDay
SELECT 1, 'Sunday' UNION ALL
SELECT 2, 'Monday' UNION ALL
SELECT 4, 'Tuesday' UNION ALL
SELECT 8, 'Wednesday' UNION ALL
SELECT 16, 'Thursday' UNION ALL
SELECT 32, 'Friday' UNION ALL
SELECT 64, 'Saturday';
WITH myCTE
AS(
SELECT sched.name AS 'scheduleName'
, sched.schedule_id
, jobsched.job_id
, CASE
WHEN sched.freq_type = 1
THEN 'Once'
WHEN sched.freq_type = 4
AND sched.freq_interval = 1
THEN 'Daily'
WHEN sched.freq_type = 4
THEN 'Every ' + CAST(sched.freq_interval AS VARCHAR(5)) + ' days'
WHEN sched.freq_type = 8 THEN
REPLACE( REPLACE( REPLACE((
SELECT maskValue
FROM #weekDay AS x
WHERE sched.freq_interval & x.mask <> 0
ORDER BY mask FOR XML RAW)
, '"/><row maskValue="', ', '), '<row maskValue="', ''), '"/>', '')
+ CASE
WHEN sched.freq_recurrence_factor <> 0
AND sched.freq_recurrence_factor = 1
THEN '; weekly'
WHEN sched.freq_recurrence_factor <> 0
THEN '; every '
+ CAST(sched.freq_recurrence_factor AS VARCHAR(10)) + ' weeks' END
WHEN sched.freq_type = 16 THEN 'On day '
+ CAST(sched.freq_interval AS VARCHAR(10)) + ' of every '
+ CAST(sched.freq_recurrence_factor AS VARCHAR(10)) + ' months'
WHEN sched.freq_type = 32 THEN
CASE
WHEN sched.freq_relative_interval = 1 THEN 'First'
WHEN sched.freq_relative_interval = 2 THEN 'Second'
WHEN sched.freq_relative_interval = 4 THEN 'Third'
WHEN sched.freq_relative_interval = 8 THEN 'Fourth'
WHEN sched.freq_relative_interval = 16 THEN 'Last'
END +
CASE
WHEN sched.freq_interval = 1 THEN ' Sunday'
WHEN sched.freq_interval = 2 THEN ' Monday'
WHEN sched.freq_interval = 3 THEN ' Tuesday'
WHEN sched.freq_interval = 4 THEN ' Wednesday'
WHEN sched.freq_interval = 5 THEN ' Thursday'
WHEN sched.freq_interval = 6 THEN ' Friday'
WHEN sched.freq_interval = 7 THEN ' Saturday'
WHEN sched.freq_interval = 8 THEN ' Day'
WHEN sched.freq_interval = 9 THEN ' Weekday'
WHEN sched.freq_interval = 10 THEN ' Weekend'
END
+ CASE
WHEN sched.freq_recurrence_factor <> 0
AND sched.freq_recurrence_factor = 1
THEN '; monthly'
WHEN sched.freq_recurrence_factor <> 0
THEN '; every '
+ CAST(sched.freq_recurrence_factor AS VARCHAR(10)) + ' months'
END
WHEN sched.freq_type = 64 THEN 'StartUp'
WHEN sched.freq_type = 128 THEN 'Idle'
END AS 'frequency'
, ISNULL('Every ' + CAST(sched.freq_subday_interval AS VARCHAR(10)) +
CASE
WHEN sched.freq_subday_type = 2 THEN ' seconds'
WHEN sched.freq_subday_type = 4 THEN ' minutes'
WHEN sched.freq_subday_type = 8 THEN ' hours'
END, 'Once') AS 'subFrequency'
, REPLICATE('0', 6 - LEN(sched.active_start_time))
+ CAST(sched.active_start_time AS VARCHAR(6)) AS 'startTime'
, REPLICATE('0', 6 - LEN(sched.active_end_time))
+ CAST(sched.active_end_time AS VARCHAR(6)) AS 'endTime'
, REPLICATE('0', 6 - LEN(jobsched.next_run_time))
+ CAST(jobsched.next_run_time AS VARCHAR(6)) AS 'nextRunTime'
, CAST(jobsched.next_run_date AS CHAR(8)) AS 'nextRunDate'
FROM msdb.dbo.sysschedules AS sched
JOIN msdb.dbo.sysjobschedules AS jobsched
ON sched.schedule_id = jobsched.schedule_id
WHERE sched.enabled = 1
)
SELECT job.name AS [Job Name]
, CASE WHEN job.enabled = 1 THEN 'Enabled' ELSE 'Disabled' END AS [Job Status]
, COALESCE(sched.subFrequency, '') AS [Frequency]
, COALESCE(jh.last_duration, '') AS [Last Run Duration]
, COALESCE(jh.last_execution_start, '') AS [Last Run Time/Date]
FROM msdb.dbo.sysjobs AS job
LEFT JOIN myCTE AS sched
ON job.job_id = sched.job_id
LEFT JOIN #jobHistory AS jh
ON job.job_id = jh.job_id
WHERE jh.last_execution_start >= DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))
AND job.name like '%MAINTENANCE - BACKUP%'
ORDER BY nextRunDate;
but although the results show the expected 'Failed' jobs, the 'Disabled' jobs are missing. I have also had help with this, as I have no SQL experience.
This Query has been created to check the Job History of roughtly 5/10 Backup Jobs within a 24 hour period, noting all the Failures (even if the last Run Succeeded). The seconds on the [Last Run Time/Date] also seem to be off, showing as soemthign like '50:00.0'
I also need a new column for the [Last Run Outcome] - to show if the Job 'Failed/Succeeded' as a Status.
Please let me know if you require any further information or a PasteBin of my code.

How to count up a single character in multiple fields in SQL

HI i have a table 'TableCustomers' and within this table are many fields titled 'Name1' 'Name2''Name3'.... 'Name40' some of these fields just have the letter 'x' i want to know how many 'x' are there in all 40 fields
One possible solution is something like;
SELECT
CASE WHEN [Name] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name1] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name2] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name3] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name4] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name5] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name6] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name7] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name8] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name9] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name10] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name11] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name12] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name13] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name14] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name15] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name16] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name17] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name18] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name19] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name20] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name21] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name22] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name23] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name24] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name25] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name26] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name27] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name28] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name29] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name30] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name31] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name32] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name33] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name34] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name35] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name36] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name37] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name38] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name39] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name40] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name41] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name42] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name43] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name44] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name45] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name46] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name47] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name48] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name49] = 'x' THEN 1 ELSE 0 END +
CASE WHEN [Name50] = 'x' THEN 1 ELSE 0 END
FROM [TableCustomers]
I generated this using an application called Nimble Text (http://nimbletext.com/) though you could use dynamic SQL along with the sys.columns view to generate this statement within SQL server, if the columns of the table change. Let me know if you would like an example of this...
You may try something like this:
select len(name00 + name01 + .. + name40) - len(replace(name00 + name01 + .. + name40, 'x', ''))
from yourTable;

Nested case limit

I'm trying to use nested case but SQL is giving me an error on 10 limit. Below is my sql. Do you have any suggestions for me?
ALTER VIEW [dbo].[vwOpti_ChannelPreference] AS
SELECT SUB.*,
CASE WHEN PCYCResponse + JBIResponse > 1 THEN 'SF Multi'
ELSE CASE WHEN MDLResponse + SermoResponse + BioPharmResponse + MedscapeResponse + PharmaConnectResponse + THResponse
+ OtherResponse > 1 THEN 'MCM Multi'
ELSE CASE WHEN MDLResponse + SermoResponse + BioPharmResponse + MedscapeResponse + PharmaConnectResponse + THResponse
+ PCYCResponse + JBIResponse + OtherResponse > 1 THEN 'SF & MCM Multi'
ELSE CASE WHEN MDLResponse + SermoResponse + BioPharmResponse + MedscapeResponse + PharmaConnectResponse + THResponse
+ PCYCResponse + JBIResponse + OtherResponse = 0 THEN 'None'
ELSE CASE WHEN MDLResponse = 1 THEN 'MDL'
ELSE CASE WHEN SermoResponse = 1 THEN 'Sermo'
ELSE CASE WHEN BioPharmResponse = 1 THEN 'BioPharmCommunications'
ELSE CASE WHEN MedscapeResponse = 1 THEN 'Medscape'
ELSE CASE WHEN PharmaConnectResponse = 1 THEN 'PharmaConnect'
ELSE CASE WHEN THResponse = 1 THEN 'Targeted Healthcare'
ELSE CASE WHEN PCYCResponse = 1 THEN 'PCYC'
ELSE CASE WHEN JBIResponse = 1 THEN 'JBI'
ELSE CASE WHEN OtherResponse = 1 THEN 'Other'
END END END END END END END END END END END END AS ChannelPref
FROM ( SELECT CC.*,
MAX(CASE WHEN MTE.DesignVendor = 'MDL' THEN 1 ELSE 0 END) AS MDLResponse,
MAX(CASE WHEN MTE.DesignVendor = 'Sermo' THEN 1 ELSE 0 END) AS SermoResponse,
MAX(CASE WHEN MTE.DesignVendor = 'BioPharmCommunications' THEN 1 ELSE 0 END) AS BioPharmResponse,
MAX(CASE WHEN MTE.DesignVendor = 'Medscape' THEN 1 ELSE 0 END) AS MedscapeResponse,
MAX(CASE WHEN MTE.DesignVendor = 'PharmaConnect' THEN 1 ELSE 0 END) AS PharmaConnectResponse,
MAX(CASE WHEN MTE.DesignVendor = 'Targeted Healthcare' THEN 1 ELSE 0 END) AS THResponse,
MAX(CASE WHEN MTE.DesignVendor = 'PCYC' THEN 1 ELSE 0 END) AS PCYCResponse,
MAX(CASE WHEN MTE.DesignVendor = 'JBI' THEN 1 ELSE 0 END) AS JBIResponse,
MAX(CASE WHEN MTE.DesignVendor NOT IN ('MDL','Sermo', 'BioPharmCommunications', 'Medscape', 'PharmaConnect',
'Targeted Healthcare', 'PCYC', 'JBI') THEN 1 ELSE 0 END) AS OtherResponse
--SELECT DISTINCT MTE.CHANNELNAME
FROM slice_CampaignContact CC
--LEFT JOIN slice_MktgTactic MTI ON I.MktgTacticID = MTI.MktgTacticID AND I.SliceDate = MTI.SliceDate
LEFT JOIN slice_Engagements E ON CC.ContactID = E.ContactID AND CC.SliceDate = E.SliceDate
LEFT JOIN slice_MktgTactic MTE ON E.MktgTacticID = MTE.MktgTacticID AND E.SliceDate = MTE.SliceDate
GROUP BY CC.SliceDate, CC.BrandCd, CC.ContactID, CC.SyncID, CC.FirstName, CC.LastName, CC.CampaignName,
ClientSegment, ControlSegmentName) SUB
You don't need the ELSE CASE every time -- that is just the way CASE works -- each WHEN is only checked on when prior WHENs fail. Like this:
SELECT SUB.*,
CASE
WHEN PCYCResponse + JBIResponse > 1 THEN 'SF Multi'
WHEN MDLResponse + SermoResponse + BioPharmResponse + MedscapeResponse + PharmaConnectResponse + THResponse + OtherResponse > 1 THEN 'MCM Multi'
WHEN MDLResponse + SermoResponse + BioPharmResponse + MedscapeResponse + PharmaConnectResponse + THResponse + PCYCResponse + JBIResponse + OtherResponse > 1 THEN 'SF & MCM Multi'
WHEN MDLResponse + SermoResponse + BioPharmResponse + MedscapeResponse + PharmaConnectResponse + THResponse + PCYCResponse + JBIResponse + OtherResponse = 0 THEN 'None'
WHEN MDLResponse = 1 THEN 'MDL'
WHEN SermoResponse = 1 THEN 'Sermo'
WHEN BioPharmResponse = 1 THEN 'BioPharmCommunications'
WHEN MedscapeResponse = 1 THEN 'Medscape'
WHEN PharmaConnectResponse = 1 THEN 'PharmaConnect'
WHEN THResponse = 1 THEN 'Targeted Healthcare'
WHEN PCYCResponse = 1 THEN 'PCYC'
WHEN JBIResponse = 1 THEN 'JBI'
WHEN OtherResponse = 1 THEN 'Other'
ELSE 'Woah, nothing matched'
END AS ChannelPref
FROM ( SELECT CC.*, -- etc

Calculations in SQL and preventing Divide By Zero

I am trying to rework a query that is based on cursors.
The query calculates certain stats based on multiple values. In the snippet below the first, second and third CASE works out the happiness of Unit1. Any of these fields are 0 (they can never be NULL) I will get a Divide by Zero error. I could just add 1 to each field (Unit2 + 1) / (Unit1 + 1) and that will stop the error. However, it seems like a bodge and it will potentially give the incorrect result. ie. Unit1 needs the same amount of Unit2 to keep them happy. If I have one Unit1 and no Unit2 this bodge will give 100% happy for that check. So my first problem is how do I prevent the divide by zero but not distort the results. Each CASE gives me a % happy
Select
CASE WHEN ((Unit2 / Unit1) * 100) > 100 Then 100 Else ((Unit2 / Unit1) * 100) END Unit1Happy1,
CASE WHEN ((Stock3 / (Unit1 * 2)) * 100) > 100 Then 100 Else ((Stock3 / (Unit1 * 2)) * 100) END Unit1Happy2,
CASE WHEN (((Drug3 + (Drug1 / 2)) / Unit1) * 100) > 100 Then 100 Else (((Drug3 + (Drug1 / 2)) / Unit1) * 100) END Unit1Happy3,
CASE WHEN (((Weapon6 + Weapon7 + Weapon8 + Weapon9) / Unit2) * 100) > 100 Then 100 ELSE (((Weapon6 + Weapon7 + Weapon8 + Weapon9) / Unit2) * 100) END Unit2Happ1,
CASE WHEN (((Stock2 + (Stock1 / 2)) / Unit2) * 100) > 100 Then 100 Else (((Stock2 + (Stock1 / 2)) / Unit2) * 100) END Unit2Happ2
FROM tblUserFiles
My next problem is that I need to take to lowest value for each UnitHappiness and store that value in the table. So in tblUserFiles are 5 fields Unit1Happ, Unit2Happ .... Unit5Happ. Looking at the above query if Unit1Happy1 is the lowest figure I store that figure into Unit1Happ, If Unit2Happy is the lowest I store that etc.
My record Identifier is UserId and I need to run this for a given UserId or for the whole table.
What I am basically asking is:
What is the best method to identify the lowest value of each Unit
calculation?
What is the best way to prevent the divide by zero
error?
Can I approach this problem in a better way?
Update
I am working through the suggestions posted in the answers below. As this is just a training exercise it may take a while. I do have a working query that gives the results I am looking for I am just not sure if the suggested answers would be more efficient.
Update tblUserFiles Set Unit1Happ = happyvals.Unit1Happiness, Unit2Happ = happyvals.Unit2Happiness, Unit3Happ = happyvals.Unit3Happiness, Unit4Happ = happyvals.Unit4Happiness, Unit5Happ = happyvals.Unit5Happiness FROM
(SELECT ch.UserId,
Case When ch.Unit1Happy1 < ch.Unit1Happy2 And ch.Unit1Happy1 < ch.Unit1Happy3 Then ch.Unit1Happy1
When ch.Unit1Happy2 < ch.Unit1Happy1 And ch.Unit1Happy2 < ch.Unit1Happy3 Then ch.Unit1Happy2
Else ch.Unit1Happy3
End As Unit1Happiness,
CASE WHEN ch.Unit2Happy1 > ch.Unit2Happy2 THEN ch.Unit2Happy1
ELSE ch.Unit2Happy2
END AS Unit2Happiness,
ch.Unit3Happy1 AS Unit3Happiness,
ch.Unit4Happy1 AS Unit4Happiness,
ch.Unit5Happy1 AS Unit5Happiness
FROM
(
Select
UserId,
CASE WHEN Unit2 = 0 OR Unit1 = 0 THEN 0
WHEN ((Unit2 / Unit1) * 100) > 100 Then 100
ELSE ((Unit2 / Unit1) * 100)
END Unit1Happy1,
CASE WHEN Stock3 = 0 OR Unit1 = 0 THEN 0
WHEN ((Stock3 / (Unit1 * 2)) * 100) > 100 THEN 100
ELSE ((Stock3 / (Unit1 * 2)) * 100)
END Unit1Happy2,
CASE WHEN Unit1 = 0 THEN 0
WHEN Drug3 = 0 AND Drug1 = 0 THEN 0
WHEN Drug1 = 0 THEN
CASE WHEN (Drug3 / Unit1) * 100 > 100 THEN 100
ELSE (Drug3 / Unit1) * 100
END
WHEN Drug3 = 0 THEN
CASE WHEN (Drug1 / 2) / Unit1 > 100 THEN 100
ELSE (Drug1 / 2) / Unit1
END
ELSE
CASE WHEN (((Drug3 + (Drug1 / 2)) / Unit1) * 100) > 100 THEN 100
ELSE (((Drug3 + (Drug1 / 2)) / Unit1) * 100)
END
END Unit1Happy3,
CASE WHEN Unit2 = 0 THEN 0
WHEN (Weapon6 + Weapon7 + Weapon8 + Weapon9) = 0 THEN 0
WHEN (((Weapon6 + Weapon7 + Weapon8 + Weapon9) / Unit2) * 100) > 100 THEN 100
ELSE (((Weapon6 + Weapon7 + Weapon8 + Weapon9) / Unit2) * 100)
END Unit2Happy1,
CASE WHEN Unit2 = 0 THEN 0
WHEN Stock1 = 0 AND Stock2 = 0 THEN 0
WHEN Stock1 = 0 THEN
CASE WHEN ((Stock2 / Unit2) * 100) > 100 THEN 100
ELSE ((Stock2 / Unit2) * 100)
END
WHEN Stock2 = 0 THEN
CASE WHEN (((Stock1 / 2) / Unit2) * 100) > 100 THEN 100
ELSE (((Stock1 / 2) / Unit2) * 100)
END
WHEN (((Stock2 + (Stock1 / 2)) / Unit2) * 100) > 100 THEN 100
ELSE (((Stock2 + (Stock1 / 2)) / Unit2) * 100)
END Unit2Happy2,
CASE WHEN Unit2 = 0 OR Unit3 = 0 THEN 0
WHEN ((Unit2 / Unit3) * 100) > 100 THEN 100
ELSE ((Unit2 / Unit3) * 100)
END Unit3Happy1,
CASE WHEN Unit2 = 0 OR Unit4 = 0 THEN 0
WHEN ((Unit2 / Unit4) * 100) > 100 THEN 100
ELSE ((Unit2 / Unit4) * 100)
END Unit4Happy1,
CASE WHEN Unit2 = 0 OR Unit5 = 0 THEN 0
WHEN ((Unit2 / Unit5) * 100) > 100 THEN 100
ELSE ((Unit2 / Unit5) * 100)
END Unit5Happy1
FROM tblUserFiles) ch) happyvals
Join tblUserFiles ON tblUserFiles.UserID = happyvals.UserID
put a nullif(Unit1, 0) around every divide by group ?
Something like this.
The idea is to wrap your division in a UDF (scalar user defined function)....and use the "Max(v)" trick.
The code below may not be perfect, I've supplying the idea.
Cursors are horrible performers, 99.9% of the time. Try to solve this without cursors.
/* or Create */
ALTER FUNCTION dbo.udfSafeDivision (#num float , #denom float)
RETURNS float
AS
BEGIN
declare #returnValue float
select #returnValue = 0
if(isnull(#denom,0) != 0)
BEGIN
select #returnValue = convert(float, convert(float, #num)/convert(float, #denom))
END
return #returnValue
END
GO
IF OBJECT_ID('tempdb..#TableOne') IS NOT NULL
begin
drop table #TableOne
end
CREATE TABLE #TableOne
(
SurrogateKey int IDENTITY(1001, 1),
Unit1 int ,
Unit2 int ,
Stock1 int ,
Stock2 int ,
Stock3 int ,
Drug1 int ,
Drug3 int ,
Weapon6 int , Weapon7 int , Weapon8 int , Weapon9 int
)
Insert into #TableOne (Unit1, Unit2, Stock1, Stock2 , Stock3 , Drug1, Drug3 , Weapon6 , Weapon7 , Weapon8 , Weapon9)
select 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
UNION ALL select 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
UNION ALL select 1 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
UNION ALL select 1 , 2 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
UNION ALL select 1 , 2 , 3 , 4 , 0 , 0 , 0 , 0 , 0 , 0 , 0
UNION ALL select 1 , 2 , 3 , 4 , 5 , 0 , 0 , 0 , 0 , 0 , 0
UNION ALL select 1 , 2 , 3 , 4 , 5 , 6 , 0 , 0 , 0 , 0 , 0
UNION ALL select 1 , 2 , 3 , 4 , 5 , 6 , 7 , 0 , 0 , 0 , 0
UNION ALL select 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 0 , 0 , 0
UNION ALL select 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 0 , 0
UNION ALL select 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 0
UNION ALL select 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11
UNION ALL select 5 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
UNION ALL select 5 , 0 , 0 , 0 , 5 , 0 , 0 , 0 , 0 , 0 , 0
UNION ALL select 10 , 0 , 0 , 0 , 0 , 5 , 10 , 0 , 0 , 0 , 0
UNION ALL select 0 , 1 , 0 , 0 , 0 , 5 , 10 , 10 , 20 , 30 , 40
UNION ALL select 0 , 50 , 20 , 10 , 0 , 0 , 0 , 0 , 0 , 0 , 0
SELECT
(SELECT Max(v)
FROM (VALUES (Unit1Happy1), (Unit1Happy2), (Unit1Happy3), (Unit2Happ1), (Unit2Happ2)) AS value(v)) as [MaxValue]
, '--------' as Sep1
, derived1.*
FROM
(
Select
CASE WHEN ((dbo.udfSafeDivision(Unit2 , Unit1)) * 100) > 100 Then 100 Else (dbo.udfSafeDivision(Unit2 , Unit1) * 100) END Unit1Happy1,
CASE WHEN (dbo.udfSafeDivision(Stock3 , (Unit1 * 2)) * 100) > 100 Then 100 Else (dbo.udfSafeDivision(Stock3 , (Unit1 * 2)) * 100) END Unit1Happy2,
CASE WHEN (dbo.udfSafeDivision((Drug3 + (Drug1 / 2)) , Unit1) * 100) > 100 Then 100 Else (dbo.udfSafeDivision((Drug3 + (Drug1 / 2)) , Unit1) * 100) END Unit1Happy3,
CASE WHEN (dbo.udfSafeDivision((Weapon6 + Weapon7 + Weapon8 + Weapon9) , Unit2) * 100) > 100 Then 100 ELSE (dbo.udfSafeDivision((Weapon6 + Weapon7 + Weapon8 + Weapon9) , Unit2) * 100) END Unit2Happ1,
CASE WHEN (dbo.udfSafeDivision((Stock2 + (Stock1 / 2)) , Unit2) * 100) > 100 Then 100 Else (dbo.udfSafeDivision((Stock2 + (Stock1 / 2)) , Unit2) * 100) END Unit2Happ2
/* the below is to debug */
, '--' as Sep1
, Unit1, Unit2, Stock1, Stock2 , Stock3 , Drug1, Drug3 , Weapon6 , Weapon7 , Weapon8 , Weapon9
, dbo.udfSafeDivision(Unit2 , Unit1) as Div1
, dbo.udfSafeDivision(Stock3 , (Unit1 * 2)) as Div3
FROM #TableOne
) as derived1
IF OBJECT_ID('tempdb..#TableOne') IS NOT NULL
begin
drop table #TableOne
end