Incorrect syntax near '=' - sql

DECLARE #COUNT_P INT
DECLARE #COUNT_S INT
SELECT MEMBNO,
CASE
WHEN TYPCOD = 'P' THEN #COUNT_P = #COUNT_P + 1
END AS C_P,
CASE
WHEN TYPCOD = 'S' THEN #COUNT_S = #COUNT_S + 1
END AS C_S
FROM #TEMP2
GROUP BY TYPCOD
The error that I am getting is
Msg 102, Level 15, State 1, Line 8
Incorrect syntax near '='.

SELECT MEMBNO,
SUM(CASE
WHEN TYPCOD = 'P' THEN 1 ELSE 0 END) AS C_P,
SUM(CASE
WHEN TYPCOD = 'S' THEN 1 ELSE 0 END) AS C_S
FROM #TEMP2
GROUP BY MEMBNO

You cannot increment values like that in SQL Server. A SELECT either returns values or sets variables, but not both.
DECLARE #COUNT_P INT;
DECLARE #COUNT_S INT;
If you want to set the total number for the two types, then:
select #count_p = sum(case when typecode = 'P' then 1 else 0 end),
#count_s = sum(case when typecode = 'S' then 1 else 0 end)
from #TEMP2;

Related

T-SQL exactly 1 condition is true out of a set of conditions

What is the simplest way to express in T-SQL that only 1 and exactly 1 of a number of boolean conditions is true (needs to be usable in a CHECK constraint)?
XOR works for 2 conditons, eg A XOR B will insure that exactly 1 is set but it does not work for 3 conditions:
One solution would be to get some kind of collection out of them, filter on the conditions being true, perform and aggregate/sum and check that the result is equal to 1.
I would structure your CHECK along the lines of:
CHECK (
CASE WHEN <condition 1> THEN 1 ELSE 0 END +
CASE WHEN <condition 2> THEN 1 ELSE 0 END +
CASE WHEN <condition 3> THEN 1 ELSE 0 END
= 1
)
It's slightly verbose but it is hopefully readable to see what your intention was. It also extends to other similar requirements more easily than XOR (e.g. "exactly 2 out of 5 conditions must be matched" can follow the same structure)
For SQL Server 2012 or later, you can be slight more concise with IIF:
CHECK (
IIF(<condition 1>,1,0) +
IIF(<condition 2>,1,0) +
IIF(<condition 3>,1,0)
= 1
)
Shamelessly taken from this SO question, a general formula for an exclusive OR between three variables can be written as:
(a ^ b ^ c) && !(a && b && c)
We can express this in SQL Server as:
(A XOR B XOR C) AND NOT (A AND B AND C)
Note that this only works for three variables, and does not generalize to higher numbers. If you have more than three variables, you'll have to do more work.
Assuming that all your conditions are represented as BIT columns, you can have a constraint with the format:
alter table [table_name] add constraint [constraint_name]
check ( ( a ^ b ^ c ) = 1 AND NOT ( a & b & c ) = 1 )
Doing this, you can also then use the same conditions in a case statement, like:
select a, b, c,
case when (( a ^ b ^ c ) = 1 AND NOT ( a & b & c ) = 1) then 1
else 0 end
as true_or_false
from [table_name]
Putting this together, we can demo it with a script like:
create table #bits (a bit, b bit, c bit)
create table #bits2 (a bit, b bit, c bit)
alter table #bits2 add constraint ck_xor
check ( ( a ^ b ^ c ) = 1 AND NOT ( a & b & c ) = 1 )
insert into #bits
values
( 0, 0, 0 ), ( 0, 0, 1 ), ( 0, 1, 0 ), ( 0, 1, 1 ), ( 1, 0, 0 ), ( 1, 0, 1 ), ( 1, 1, 0 ), ( 1, 1, 1 )
select a, b, c,
case when ( a ^ b ^ c ) = 1 AND NOT ( a & b & c ) = 1 then 1
else 0 end
as true_or_false
from #bits
insert into #bits2
select * from #bits
where ( a ^ b ^ c ) = 1 AND NOT ( a & b & c ) = 1
-- the below line will fail because of the check constraint
insert into #bits2 (a,b,c) values (1,1,0)
select * from #bits2
drop table #bits
drop table #bits2
Declare three variable #a, #b , #c and it's bit type. Where 1 is true and 0 is false. Example with all possible of bit is here.
declare #a bit, #b bit, #c bit;
set #a=1; set #b=1; set #c=1; select #a as a,#b as b,#c as c, case when #a=#b then (case when #c=1 then 1 else 0 end) else (case when #c=0 then 1 else 0 end) end as xor;
set #a=1; set #b=1; set #c=0; select #a as a,#b as b,#c as c, case when #a=#b then (case when #c=1 then 1 else 0 end) else (case when #c=0 then 1 else 0 end) end as xor;
set #a=1; set #b=0; set #c=0; select #a as a,#b as b,#c as c, case when #a=#b then (case when #c=1 then 1 else 0 end) else (case when #c=0 then 1 else 0 end) end as xor;
set #a=1; set #b=0; set #c=0; select #a as a,#b as b,#c as c, case when #a=#b then (case when #c=1 then 1 else 0 end) else (case when #c=0 then 1 else 0 end) end as xor;
set #a=0; set #b=1; set #c=0; select #a as a,#b as b,#c as c, case when #a=#b then (case when #c=1 then 1 else 0 end) else (case when #c=0 then 1 else 0 end) end as xor;
set #a=0; set #b=1; set #c=0; select #a as a,#b as b,#c as c, case when #a=#b then (case when #c=1 then 1 else 0 end) else (case when #c=0 then 1 else 0 end) end as xor;
set #a=0; set #b=0; set #c=0; select #a as a,#b as b,#c as c, case when #a=#b then (case when #c=1 then 1 else 0 end) else (case when #c=0 then 1 else 0 end) end as xor;
set #a=0; set #b=0; set #c=0; select #a as a,#b as b,#c as c, case when #a=#b then (case when #c=1 then 1 else 0 end) else (case when #c=0 then 1 else 0 end) end as xor;
To reduce even more from the code duplication and make it a bit more readable something like this could be used:
(SELECT SUM(ExpressionValue)
FROM
(VALUES
(CASE WHEN 42 = 42 THEN 1 ELSE 0 END),
(CASE WHEN 42 = 42 THEN 1 ELSE 0 END),
(CASE WHEN 42 = 1 THEN 1 ELSE 0 END),
(CASE WHEN 42 = 42 THEN 1 ELSE 0 END)
) AS conditions(ExpressionValue))
=
1
Example usage:
DECLARE #say as VARCHAR(MAX) =
CASE
WHEN (
(SELECT SUM(ExpressionValue)
FROM
(VALUES
(CASE WHEN 42 = 42 THEN 1 ELSE 0 END),
(CASE WHEN 42 = 42 THEN 1 ELSE 0 END),
(CASE WHEN 42 = 1 THEN 1 ELSE 0 END),
(CASE WHEN 42 = 42 THEN 1 ELSE 0 END)
) AS conditions(ExpressionValue))
=
1
) THEN 'Only one set'
ELSE 'Non only one set'
END
PRINT #say
It could still be improved if it is somehow possible to elegantly just apply the case operation similar to a map.
declare #tt table (i int, b1 bit, b2 bit, b3 bit);
insert into #tt values (1,0,0,0), (2,1,1,1), (3,1,0,0)
select i, b1, b2, b3
from #tt
where cast(b1 as tinyint) + cast(b2 as tinyint) + cast(b3 as tinyint) = 1

SQL Conversion failed when converting row number

So I've been trying to add an Dynamic Row Number column with out using Dynamic SQL. However when I try I get an error 'Conversion failed when converting character string to smalldatetime data type.'
I Know the Error is coming from in the functions So if you want to just look at the switch case in the function that is the problem, but here is the stored procedure just in case you need to see it.
I have a store procedure which looks like this:
ALTER PROCEDURE [dbo].[MMS_EdgateMainQueue]
-- Add the parameters for the stored procedure here
#OrderByColumnID int = 3,
#Skip int = 0,
#Take int = 0,
#Descending bit = 1,
#ResultCount INT OUTPUT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
Declare #UrlTitlePrefix varchar(2080) = '<a href="/Title/PageByExtTitleID?ActionName=Edgate&ExtTitleID='
Declare #UrlProducerPrefix varchar(2080) = '<a href="/Producers/ByExtVendorID?ActionName=Details&ExtVendorID='
Declare #Urlmidfix varchar(100) = '">'
Declare #UrlPostFix varchar(100) = '</a>'
SELECT TOP (#Take)
[row_numb],
#UrlTitlePrefix + ExtTitleID + #Urlmidfix + ExtTitleID + #UrlPostFix as [Item #],
f.Title as Name,
#UrlProducerPrefix + f.ExtVendorID + #Urlmidfix + f.DisplayName + #UrlPostFix as Producer,
f.Created as Created,
isnull(f.Academic, '') as Academic,
isnull(f.Sears,'') as Sears,
isnull(f.Editor, '') as Editor,
CONVERT(INT, f.[Copy]) AS Copy,
f.[Segment],
CONVERT(INT, f.[Taxonomy]) AS Taxonomy,
f.[Priority]
FROM EdgateNewTitlesInnerQuery(#OrderByColumnID, #Descending) as f
Where f.[row_numb] Between ((#Skip * #Take) + 1) and ((#Skip + 1) * #Take) order by f.[row_numb]
END
And The Inner Function Looks Like:
ALTER FUNCTION [dbo].[EdgateNewTitlesInnerQuery]
(
#OrderByColumnID int,
#Descending bit
)
RETURNS TABLE
AS
RETURN
(
SELECT DISTINCT
v.ExtVendorID,
t.ID,
t.ExtTitleID,
t.Title,
v.DisplayName,
t.Created,
ecs.Title as [Academic],
ssub.Title as [Sears],
etw.EditorName as [Editor],
etw.CopyDone AS [Copy],
etw.SegmentsStatus as [Segment],
etw.TaxonomyDone AS [Taxonomy],
CASE WHEN wft.[Priority] is null THEN 0 ELSE wft.[Priority] END as [Priority],
--row_number() OVER (ORDER BY t.Created DESC) AS [row_number]
row_number() OVER (ORDER BY
CASE #OrderByColumnID WHEN 0 THEN t.ExtTitleID
WHEN 1 THEN t.Title
WHEN 2 THEN v.DisplayName
WHEN 3 THEN t.Created
WHEN 4 THEN ecs.Title
WHEN 5 THEN ssub.Title
WHEN 6 THEN etw.EditorName
WHEN 7 THEN etw.CopyDone
WHEN 8 THEN etw.SegmentsStatus
WHEN 9 THEN etw.TaxonomyDone
WHEN 10 THEN CASE WHEN wft.[Priority] is null THEN 0 ELSE wft.[Priority] END
ELSE t.Created
END DESC ) AS [row_numb]
FROM [Title] t
join EdgateTitleWorkflow etw on etw.FK_TitleID = t.ID
join Vendor v on v.ExtVendorID = t.ProducerID
join CollectionItem i on i.TitleID = t.ID and i.CollectionID = 16
left join [EdgateSuggestedAcademicSubject] esas on esas.FK_TitleID = t.ID and esas.isPrimary = 1
left join EC_Subject ecs on ecs.ID = esas.FK_SubjectID
left join [FMGSuggestedSears] fss on fss.FK_TitleID = t.ID and fss.isPrimary = 1
left join [FMGSearsSubjects] ssub on ssub.ID = fss.SearsSubjectID and ssub.ParentID is null
left join [WorkFlow_Tracker] wft on wft.TitleID = t.ID
where (etw.CopyDone = 0 or etw.TaxonomyDone = 0 or etw.SegmentsStatus = 0)
)
I've tried passing this in as a string originally but it just didn't sort at all. So I was looking at similar problems and tried this solution Here
but my switch Case is now throwing a Conversion Error. Does anyone have an Idea on how to fix this?
The problem is that case is an expression that returns one type, defined during compilation. You can fix this with a separate case for each key. I think this is the statement you want:
row_number() OVER (ORDER BY (CASE WHEN #OrderByColumnID = 0 THEN t.ExtTitleID END),
(CASE WHEN #OrderByColumnID = 1 THEN t.Title END),
(CASE WHEN #OrderByColumnID = 2 THEN v.DisplayName END),
(CASE WHEN #OrderByColumnID = 3 THEN t.Created END),
(CASE WHEN #OrderByColumnID = 4 THEN ecs.Title END),
(CASE WHEN #OrderByColumnID = 5 THEN ssub.Title END),
(CASE WHEN #OrderByColumnID = 6 THEN etw.EditorName END),
(CASE WHEN #OrderByColumnID = 7 THEN etw.CopyDone END),
(CASE WHEN #OrderByColumnID = 8 THEN etw.SegmentsStatus END),
(CASE WHEN #OrderByColumnID = 9 THEN etw.TaxonomyDone END),
(CASE WHEN #OrderByColumnID = 10 THEN COALESCE(wft.[Priority], 0) END)
t.Created DESC
)

IN Condition Issue in SQL Server

I want to use multiple inputs in a procedure in IN condition. How can I do this?
Below is my query code.
Declare #iM_ID varchar(100)
set #iM_ID='20,22,24,25'
select #iM_ID
SELECT M.M_ID,
SUM(CASE WHEN CT_ID=1
THEN 1
ELSE 0 END) AS "Secret_Coupons",
SUM(CASE WHEN CT_ID=2
THEN 1
ELSE 0 END) AS "Hot_Coupons"
FROM C_Master
INNER JOIN M_Master
ON C_Master.M_ID=M_Master.M_ID
and datediff(hh,getutcdate(),End_Datetime)>0
and M_Master.M_ID in (#iM_ID)
GROUP BY M_Master.M_ID
Try like this
DECLARE #sql AS VARCHAR(MAX)
Declare #iM_ID varchar(100)
SET #iM_ID='20,22,24,25'
SET #sql = 'SELECT M.M_ID,SUM(CASE WHEN CT_ID=1 THEN 1 ELSE 0 END) AS "Secret_Coupons",
SUM(CASE WHEN CT_ID=2 THEN 1 ELSE 0 END) AS "Hot_Coupons"
FROM C_Master INNER JOIN M_Master ON C_Master.M_ID=M_Master.M_ID
AND datediff(hh,getutcdate(),End_Datetime)>0 AND
M_Master.M_ID IN ( ' + #iM_ID + ')
GROUP BY M_Master.M_ID'
EXECUTE #sql

How to Convert Centesimal to Sexagesimal

I have this query: I need convert the centesimal value from the database to sexagesimal (minutes)
SELECT
DISTINCT RD_MAT,
SUM(CASE WHEN RD_PD IN ('421') THEN RD_HORAS ELSE 0 END) AS 'ATRASOS',
SUM(CASE WHEN RD_PD IN ('420') THEN RD_HORAS ELSE 0 END) AS 'FALTAS',
SUM(CASE WHEN RD_PD IN ('084') THEN RD_HORAS ELSE 0 END) AS 'H.EXTRA 100%',
SUM(CASE WHEN RD_PD IN ('080') THEN RD_HORAS ELSE 0 END) AS 'H.EXTRA 50% ',
SUM(CASE WHEN RD_PD IN ('082') THEN RD_HORAS ELSE 0 END) AS 'H.EXTRA NOTURNA'
FROM SRD020
INNER JOIN SRV020 ON RD_PD = RV_COD
AND SRV020.D_E_L_E_T_ <> '*'
AND SRD020.D_E_L_E_T_ <> '*'
AND RD_MAT = '000123'
WHERE LEFT(RD_DATPGT,6) = '201304'
GROUP BY RD_MAT
The return of H.EXTRA 100% in centesimal is 16:53. But in minutes is 16:49.
Example: 40 + 40 = 80 in centesimal. 40 + 40 = 1:20 in sexagesimal. I need this value.
So, it looks like you're going for something like this. I'm casting to VARCHAR for output purposes, which you of course do not have to do.
DECLARE #value1 INT, #value2 INT
SET #value1 = 40
SET #value2 = 50
SELECT CAST(FLOOR((#value1+#value2)/60) AS VARCHAR(50)) + ':' + CAST((#value1+#value2)%60 AS VARCHAR(50))
Declare #h Varchar(5)='16:53'
Select Cast(DateAdd(SS,CAST(REPLACE(#h,':','.') as Float)*60,0) as Time)
>>> 00:16:31.0000000

SQL case when set variable

I am trying to set 2 declared variable with case when blocks
Here's my code:
DECLARE #like bit,#dislike bit
if exists
( select *
,#like = (CASE WHEN likeordislike = 1 THEN 'true' ELSE 'false' END)
,#dislike=(CASE WHEN likeordislike = 0 THEN 'true' ELSE 'false' END)
from likeordislike
)
But when I execute query throws errors:
Msg 102, Level 15, State 1, Line 4
Incorrect syntax near '='.
Everything is ok? Couldn't understand
if (select count(*) from likeordislike where user = #user and comment_id = #comment_id) = 0
begin
insert into likeordislike etc
end
else
update likeordislike etc
end