MySql select statement with conditional where clause - mysql

I am trying to write a MySql statement with a conditional where clause.
something like this:
set #price = 5000 ;
set #city = 1324368075;
select count(*)
from property
where case when #price is not null then
price < #price
end
and (case when #city is not null then
CityId = #city
end)
the variable should be included in the query only if it is not null.
My attempts have failed so far. Any ideas?
Edited:
Sorry I spoke too soon ysth,
these two queries are supposed to yield the same count but they dont.
Edit #2: Execution plan & indexes
Here's the query:
set #CountryId = null ;
set #CityId = 1324368075 ;
set #StateProvince = null ;
set #CategoryId = null ;
set #TransactionTypeId = null;
set #Price = 5000;
SELECT
Count(*)
FROM
meerkat.property
WHERE
(CASE WHEN #CountryId IS NOT NULL THEN CountryId = #CountryId ELSE 1 END)
AND (CASE WHEN #CityId IS NOT NULL THEN CityId = #CityId ELSE 1 END)
AND (CASE WHEN #CategoryId IS NOT NULL THEN CategoryId = #CategoryId ELSE 1 END)
AND (CASE WHEN #StateProvince IS NOT NULL THEN StateProvince = #StateProvince ELSE 1 END)
AND (CASE WHEN #TransactionTypeId IS NOT NULL THEN TransactionTypeId = #TransactionTypeId ELSE 1 END)
AND (CASE WHEN #Price IS NOT NULL THEN Price <= #Price ELSE 1 END)
AND IsPublic = 1
AND IsBlocked = 0;
Thanks in advance

If no when conditions are met, case returns null. If you want each test to pass, you need to return a true value instead, so:
case when #price is not null then
price < #price
else 1 end
and ...

Related

How to use IF condition in storedProcedure?

I am using a condition to lock the login account after a fixed number of attempts with the wrong password. The update portion is as follows :
loginAttempts (INT(1)) is read from login account first
DECLARE LoginAttempts INT(1);
UPDATE login SET
LOGIN_ACCOUNT_STATUS = (SELECT CASE (LoginAttempts > MaxLoginAttempts) WHEN 1 THEN 'LOCKED' ELSE 'ACTIVE' END),
LOGIN_LOGIN_ATTEMPTS = (SELECT CASE (#USER_FOUND AND #PASSWORD_CORRECT) WHEN 1 THEN 0 ELSE LOGIN_LOGIN_ATTEMPTS + 1 END),
LOGIN_LAST_LOGIN_DATE = (SELECT CASE (#USER_FOUND AND #PASSWORD_CORRECT) WHEN 1 THEN TransactionDateTime ELSE LOGIN_LAST_LOGIN_DATE END),
LOGIN_LAST_LOGIN_LOCATION = null
WHERE LOGIN_EMAIL = UserEmail;
When I set MaxLoginAttmpts at 5, the account gets locked at 11 (Greater than twice maxLoginAttempts).
If I set MaxLoginAttmpts at 2, the account gets locked at 5 (Greater than twice maxLoginAttempts).
Why is this ? Any help is appreciated.
Here I am adding the full stored procedure.
CREATE DEFINER=`pubuducg`#`%` PROCEDURE `CustomerAuthenticate`(IN UserEmail VARCHAR(100), IN PassWD VARCHAR(40), IN AccStatus VARCHAR(100),IN TransactionDateTime DATETIME, IN MaxLoginAttempts INT(1))
BEGIN
DECLARE LoginUserID INT(11);
DECLARE LoginEmail VARCHAR(50);
DECLARE LoginPassword TINYTEXT;
DECLARE LoginAttempts INT(1);
DECLARE AccountStatus VARCHAR(45);
DECLARE UserRoles VARCHAR(80);
SELECT
login.LOGIN_USER_ID,
login.LOGIN_EMAIL,
login.LOGIN_PASSWORD,
login.LOGIN_ACCOUNT_STATUS,
login.LOGIN_LOGIN_ATTEMPTS,
GROUP_CONCAT(user_role.USER_ROLE_ROLE SEPARATOR ',') AS ROLES
INTO
LoginUserID,
LoginEmail,
LoginPassword,
AccountStatus,
LoginAttempts,
UserRoles
FROM login
INNER JOIN user_role ON
user_role.USER_ROLE_USER_ID = login.LOGIN_USER_ID AND user_role.USER_ROLE_STATUS = AccStatus
WHERE login.LOGIN_EMAIL = UserEmail;
SET #USER_FOUND = found_rows();
SET #PASSWORD_CORRECT = IF((LoginPassword = PassWD AND AccountStatus = AccStatus), true, false);
UPDATE login SET
LOGIN_ACCOUNT_STATUS = (SELECT CASE (LoginAttempts > MaxLoginAttempts) WHEN 1 THEN 'LOCKED' ELSE 'ACTIVE' END),
LOGIN_LOGIN_ATTEMPTS = (SELECT CASE (#USER_FOUND AND #PASSWORD_CORRECT) WHEN 1 THEN 0 ELSE LOGIN_LOGIN_ATTEMPTS + 1 END),
LOGIN_LAST_LOGIN_DATE = (SELECT CASE (#USER_FOUND AND #PASSWORD_CORRECT) WHEN 1 THEN TransactionDateTime ELSE LOGIN_LAST_LOGIN_DATE END),
LOGIN_LAST_LOGIN_LOCATION = null
WHERE LOGIN_EMAIL = UserEmail;
SELECT
IF(#USER_FOUND AND #PASSWORD_CORRECT, LoginUserID,0) AS USER_ID,
#PASSWORD_CORRECT AS AUTHENTICATED,
#USER_FOUND AS USER_EXISTS,
AccountStatus AS ACCOUNT_STATUS,
IF(#USER_FOUND AND #PASSWORD_CORRECT, 0, LoginAttempts + 1) AS LOGIN_ATTEMPTS,
IF(#USER_FOUND AND #PASSWORD_CORRECT, UserRoles,null) AS USER_ROLES;
END

SQL Server Row totals in pivot query

I am trying to make a row in the end of the result set that shows the totals.
My query is this:
SELECT
[ ] = ISNULL(CAST(GEN_idPaciente AS VARCHAR)+'-'+nombrePaciente, 'TOTAL'),
[2016-11-01] = MAX([2016-11-01]),
[2016-11-02] = MAX([2016-11-02]),
[2016-11-03] = MAX([2016-11-03]),
[2016-11-04] = MAX([2016-11-04]),
TOTAL = COUNT([2016-11-01]) + COUNT([2016-11-02]) + COUNT([2016-11-03]) + COUNT([2016-11-04])
FROM
(
SELECT GEN_Paciente.GEN_idPaciente,COALESCE(GEN_ape_paternoPaciente, '')+' '+COALESCE(GEN_ape_maternoPaciente, '')+' '+COALESCE(GEN_nombrePaciente, '') AS nombrePaciente,HOS_fechaCategorizacion,HOS_nivel_riesgoCategorizacion+CAST(HOS_nivel_dependenciaCategorizacion AS VARCHAR) as riesgoDependencia
FROM HOS_Categorizacion
INNER JOIN HOS_Hospitalizacion
ON HOS_Hospitalizacion.HOS_idHospitalizacion = HOS_Categorizacion.HOS_idHospitalizacion
INNER JOIN GEN_Paciente
ON GEN_Paciente.GEN_idPaciente = HOS_Hospitalizacion.GEN_idPaciente
WHERE HOS_nivel_riesgoCategorizacion IS NOT NULL
) src
PIVOT
(
MAX(riesgoDependencia)
for HOS_fechaCategorizacion in ([2016-11-01],[2016-11-02],[2016-11-03],[2016-11-04])
) p
GROUP BY
ROLLUP(CAST(GEN_idPaciente AS VARCHAR)+'-'+nombrePaciente)
This gives me this result:
But as you can see the totals for the rows are right but the totals for the columns are wrong because I am using MAX instead of COUNT, but I only need COUNT in the TOTAL row, the others have to be MAX, so I wrote this query:
SELECT
[ ] = ISNULL(CAST(GEN_idPaciente AS VARCHAR)+'-'+nombrePaciente, 'TOTAL'),
[2016-11-01] = CASE WHEN CAST(GEN_idPaciente AS VARCHAR)+'-'+nombrePaciente IS NOT NULL THEN MAX([2016-11-01]) ELSE COUNT([2016-11-01]) END,
[2016-11-02] = CASE WHEN CAST(GEN_idPaciente AS VARCHAR)+'-'+nombrePaciente IS NOT NULL THEN MAX([2016-11-02]) ELSE COUNT([2016-11-02]) END,
[2016-11-03] = CASE WHEN CAST(GEN_idPaciente AS VARCHAR)+'-'+nombrePaciente IS NOT NULL THEN MAX([2016-11-03]) ELSE COUNT([2016-11-03]) END,
[2016-11-04] = CASE WHEN CAST(GEN_idPaciente AS VARCHAR)+'-'+nombrePaciente IS NOT NULL THEN MAX([2016-11-04]) ELSE COUNT([2016-11-04]) END,
TOTAL = COUNT([2016-11-01]) + COUNT([2016-11-02]) + COUNT([2016-11-03]) + COUNT([2016-11-04])
FROM
(
SELECT GEN_Paciente.GEN_idPaciente,COALESCE(GEN_ape_paternoPaciente, '')+' '+COALESCE(GEN_ape_maternoPaciente, '')+' '+COALESCE(GEN_nombrePaciente, '') AS nombrePaciente,HOS_fechaCategorizacion,HOS_nivel_riesgoCategorizacion+CAST(HOS_nivel_dependenciaCategorizacion AS VARCHAR) as riesgoDependencia
FROM HOS_Categorizacion
INNER JOIN HOS_Hospitalizacion
ON HOS_Hospitalizacion.HOS_idHospitalizacion = HOS_Categorizacion.HOS_idHospitalizacion
INNER JOIN GEN_Paciente
ON GEN_Paciente.GEN_idPaciente = HOS_Hospitalizacion.GEN_idPaciente
WHERE HOS_nivel_riesgoCategorizacion IS NOT NULL
) src
PIVOT
(
MAX(riesgoDependencia)
for HOS_fechaCategorizacion in ([2016-11-01],[2016-11-02],[2016-11-03],[2016-11-04])
) p
GROUP BY
ROLLUP(CAST(GEN_idPaciente AS VARCHAR)+'-'+nombrePaciente)
But that is not working
Thanks for your help!!
If I understand this correctly you want to count all columns which are not null. In this case you should just look at the condition IS NULL and not at the actual value at all. Try this:
DECLARE #tbl TABLE(ID INT IDENTITY, val1 VARCHAR(100),val2 VARCHAR(100),val3 VARCHAR(100));
INSERT INTO #tbl VALUES
('row1_val1','row1_val2',NULL)
,('row2_val1','row2_val2','row2_val3')
,(NULL,'row2_val2',NULL)
,(NULL,NULL,'row2_val3')
,(NULL,NULL,NULL);
SELECT *
,CASE WHEN val1 IS NULL THEN 0 ELSE 1 END
+CASE WHEN val2 IS NULL THEN 0 ELSE 1 END
+CASE WHEN val3 IS NULL THEN 0 ELSE 1 END AS CountOfValNotNull
FROM #tbl
UPDATE: Add a final Totals Row
You'd need ugly fiddling with a CTE, an additional sort column, UNION ALL to add another row and a sub_select.
Use the outer-most ORDER BY to get the artificial Totals-Row to the end
hint: Use the #tbl variable from above!
WITH SortedRows AS
(
SELECT ROW_NUMBER() OVER(ORDER BY ID) AS SortColumn
,*
,CASE WHEN val1 IS NULL THEN 0 ELSE 1 END
+CASE WHEN val2 IS NULL THEN 0 ELSE 1 END
+CASE WHEN val3 IS NULL THEN 0 ELSE 1 END AS CountOfValNotNull
FROM #tbl
)
SELECT tbl1.*
FROM
(
SELECT * FROM SortedRows
UNION ALL
SELECT 999999,0,'','','',(SELECT SUM(CountOfValNotNull) FROM SortedRows)
) AS tbl1
ORDER BY tbl1.SortColumn

using a CASE within WHERE

I have code where I need to add filter into where clause that varies based on value of variable. As in example below if #X has a value of 0 then I want
to include a filter for OrderID = 10; otherwise I want to add filter for OrderID = 20 with another filter for DepartmentID either been NULL or a value of 30. This could be accomplished using a IF ELSE as below
DECLARE #X INT
-- Retrieve value for #X
IF #X = 0
BEGIN
SELECT *
FROM Customers
WHERE ProductID IS NOT NULL
AND OrderID = 10
END
ELSE
BEGIN
SELECT *
FROM Customers
WHERE ProductID IS NOT NULL
AND OrderID = 20 AND ( DepartmentID IS NULL OR DepartmentID = 30)
END
I wonder if there is someway of doing it using one SQL statement. I thought it's doable using CASE within a WHERE but SQL does not seem to allow below.
SELECT *
FROM Customers
WHERE ProductID IS NOT NULL
AND CASE WHEN #X = 0 THEN OrderID = 10 ELSE OrderID = 20 AND ( DepartmentID IS NULL OR DepartmentID = 30) END
Is there anyway of accomplishing this.
you were close,
AND OrderID = (CASE WHEN #X = 0 THEN 10 ELSE 20 END)
AND DepartmentID = (CASE WHEN #X = 0 THEN DepartmentID ELSE 30 END)
SELECT *
FROM Customers
WHERE ProductID IS NOT NULL
AND OrderID = CASE WHEN #X = 0 THEN 10 ELSE 20 END
AND ISNULL(DepartmentID,30) = CASE WHEN #X = 0 THEN ISNULL(DepartmentID,30) ELSE 30 END
You can do that without a CASE:
SELECT *
FROM Customers
WHERE ProductID IS NOT NULL
AND ((#X = 0 AND OrderID = 10) OR (#X <> 0 AND OrderID = 20 AND DepartmentID = 30))
Edit:
With the condition that you wanted to add:
SELECT *
FROM Customers
WHERE ProductID IS NOT NULL
AND ((#X = 0 AND OrderID = 10) OR (#X <> 0 AND OrderID = 20 AND (DepartmentID IS NULL OR DepartmentID = 30)))

Case When with AND?

I want to use Case When with AND condition and it is not calculating the sum properly.
For example:
SELECT DATE(`SubmitDate`),
SUM(CASE status WHEN 'New' AND `Type` = 'consumer' THEN 1 ELSE 0 END) as new_consumer,
SUM(CASE status WHEN 'New' AND `Type` = 'business' THEN 1 ELSE 0 END) as new_business
FROM report
WHERE `source` = 'net'
group by DATE(`SubmitDate`) Order by `SubmitDate` DESC
You need to use CASE WHEN [Condition] THEN... rather than a simple case expression:
SELECT DATE(`SubmitDate`),
SUM(CASE WHEN status = 'New' AND `Type` = 'consumer' THEN 1 ELSE 0 END) as new_consumer,
SUM(CASE WHEN status = 'New' AND `Type` = 'business' THEN 1 ELSE 0 END) as new_business
FROM report
WHERE `source` = 'net'
group by DATE(`SubmitDate`) Order by `SubmitDate` DESC
You should write
CASE WHEN status='New' AND `Type` = 'consumer' THEN 1 ELSE 0 END
Check the syntax of CASE WHEN

Issue with include/exclude data in my stored procedure depending of parameter

I had an issue in my stored procedure that needs to include rows or not depending on the value of a parameter
if #var_exclude = 'Y' I need to show only rows that mytable.field1 = 'N'
if #var_exclude = 'N' I need to show all rows
I'm using the following query but doesn't work properly
My code is like
#var_exclude varchar(1)
select mytable.field1, mytable.field2, mytable.field3, mytable.field4,mytable.field5
from mytable
Where mytable.field6 is null
and mytable.field1 is not null
and (mytable.state = #paramstate or #paramstate = 'ALL')
and mytable.field1 = Case when #var_exclude= 'Y' Then 'N' Else #var_exclude End
End
I'm confused!
Your logic handling #var_exclude is wrong.
When you pass #var_exclude = 'Y', then your query basically gets resolved to:
select .....
from mytable
where mytable.field6 is null
and mytable.field1 is not null
and (mytable.state = #paramstate or #paramstate = 'ALL')
and mytable.field1 = 'N'
since in this case, the when #var_exclude= 'Y' Then 'N' part of your CASE clause is used.
If you pass anything else in, then you take the value you're passing in; so if you pass in #var_exclude = 'N' then your query is resolved to:
select .....
from mytable
where mytable.field6 is null
and mytable.field1 is not null
and (mytable.state = #paramstate or #paramstate = 'ALL')
and mytable.field1 = 'N'
since in this case the Else #var_exclude of your CASE clause is used - and since #var_exclude = 'N', you get the exact same query as before....
I would probably write this procedure something like this:
CREATE PROCEDURE dbo.GetData
#paramstate VARCHAR(???),
#var_exclude CHAR(1)
AS BEGIN
IF #var_exclude = 'N' THEN
SELECT
t.field1, t.field2, t.field3, t.field4, t.field5
FROM
dbo.mytable t
WHERE
t.field6 IS NULL
AND t.field1 IS NOT NULL
AND (t.state = #paramstate OR #paramstate = 'ALL')
ELSE
SELECT
t.field1, t.field2, t.field3, t.field4, t.field5
FROM
dbo.mytable t
WHERE
t.field6 IS NULL
AND t.field1 IS NOT NULL
AND (t.state = #paramstate OR #paramstate = 'ALL')
AND t.field1 = 'N'
END
Hey in case anyone is still looking for something like this, you CAN actually do it in the where clause, you need to write an IN statement and evaluate the condition as follows:
DECLARE #Include bit
SELECT ISNULL(CASE #Include WHEN 1 THEN 1 END,0)
UNION
SELECT ISNULL(CASE #Include WHEN 1 THEN 0 END,0)
So this will evaluate to:
IF #Include = 1 THEN 0,1
ELSEIF #Include = 0 THEN 0
END
So all you have to do is write an IN clause in the WHERE clause.
SELECT * FROM store
WHERE values IN (
SELECT ISNULL(CASE #Include WHEN 1 THEN 1 END,0)
UNION
SELECT ISNULL(CASE #Include WHEN 1 THEN 0 END,0)
)
I hope this helps anyone in the future!