I need to write a query that query customer table base on first_name and/ or last_name. in my query it works for example when I run with firstname =Ann it brings all the customers with that firstname and when I run with lastname=sam brings all will that last name, but when I run with 'Ann','Sam' instead of bring only one record that is match this it brings all with firstname Ann or last same sam so it bring several records.
select * from customer
where WHERE --(CONVERT(varchar(50),decryptbykey([Account_Number]))=
#UserName or ce.Email= #UserName or Username=#UserName )
((CONVERT(varchar(50),decryptbykey([First_Name]))) =#First_Name)
and (CONVERT(varchar(50),decryptbykey([Last_Name])) =#Last_Name)
or ((CONVERT(varchar(50),decryptbykey([First_Name]))) =#First_Name)
or (CONVERT(varchar(50),decryptbykey([Last_Name])) =#Last_Name)
In this scenario I'd treat each parameter as optional. If provided then enforce the condition, otherwise skip that check. This type of query is convenient in the sense that you do not have to maintain n! versions of your query, however I must warn you this is prone to bad cached query plans.
If you experience a significant slowdown that you cannot explain you might want to tack 'OPTION (RECOMPILE)' to the end of you query. In general this may seem like a bad idea but I'd rather SQL server take an extra 5 ms each query than take 30 seconds once. Locks, database load, user experience, etc. As usual, forcing query options is generally a bad idea and should only be done if there is no other reasonable solution.
IF (#UserName_Name = '')
SET #First_Name = NULL;
IF (#First_Name = '')
SET #First_Name = NULL;
IF (#Last_Name = '')
SET #First_Name = NULL;
select *
from customer
where (#UserName IS NULL
OR Username = #UserName
OR Email = #UserName
OR CONVERT(varchar(50), decryptbykey([Account_Number])) = #UserName)
AND (#First_Name IS NULL OR CONVERT(varchar(50), decryptbykey([First_Name])) = #First_Name)
AND (#Last_Name IS NULL OR CONVERT(varchar(50), decryptbykey([First_Name])) = #Last_Name);
This might not be pretty, but it works as you describe it.
If exact match on both Firstname AND Lastname only the exact match is returned (could be more than one though). If match on only Firstname OR Lastname, all matching records are returned
SELECT * FROM customer
WHERE
(
(First_name = (CASE WHEN (First_name = #First_Name AND Last_name = #Last_Name) THEN #First_Name END))
AND
(Last_name = (CASE WHEN (First_name = #First_Name AND Last_name = #Last_Name) THEN #Last_Name END))
)
OR
(
(First_name = (CASE WHEN (First_name = #First_Name AND Last_name <> #Last_Name) THEN #First_Name END))
OR
(Last_name = (CASE WHEN (First_name <> #First_Name AND Last_name = #Last_Name) THEN #Last_Name END))
)
You'll have to add your other filters and CONVERTs yourself.
Related
I have to recreate a stored procedure which existed in DB1, and map the existing tables to new tables in the new database DB2.
In DB1, table there was column Fullname and in the new db there are two columns firstname, lastname. I could have concat but there is a user defined function also which truncates all special characters which I have to use.
How do I use the first name and last name columns as one full name column so that it fits this case statement?
I am getting the [P Name] from another table enrolled enr which is like the master table having all the names, getting names from either tables is conditioned as shown in case statement.
I tried searching all blogs and stackexchange but cannot get the desired reply.
masterfinancer = dbo.fn_RemoveSpecialChars(iif(enr.p_name = 'XXXXXXXXX,XXXXXXX(2)', 'XXXXX XXXX XXX GROUP', mv.master_vendor_name))
Sma_finace_key = iif(enr.p_name = 'XXXXXXXXX0L(2)', 1111, mv.ven_key)
[P Name] = case
when enr.p_name = 'INACTIVE ' or enr.p_name = 'UNASSIGNED'
then [P Name]
else dbo.fn_RemoveSpecialChars(enr.p_name)
end
You'll need to use the function on each separate field and join them together. Here I removed the IIF statements (which only work in SQL 2012) and created a FullName field that assumes you want "First, Last". I added COALESCE to avoid the FullName field being NULL when either the first or last names are NULL:
SELECT
masterfinancer = dbo.fn_RemoveSpecialChars(
CASE
WHEN enr.p_name = 'XXXXXXXXX,XXXXXXX(2)'
THEN 'XXXXX XXXX XXX GROUP'
ELSE mv.master_vendor_name
END)
, Sma_finace_key =
CASE
WHEN enr.p_name = 'XXXXXXXXX0L(2)'
THEN 1111
ELSE mv.ven_key
END
, [P Name] =
CASE
WHEN enr.p_name IN('INACTIVE ', 'UNASSIGNED')
THEN [P Name]
ELSE dbo.fn_RemoveSpecialChars(enr.p_name)
END
, FullName =
COALESCE(dbo.fn_RemoveSpecialChars(enr.last_name) + ', ', '') +
COALESCE(dbo.fn_RemoveSpecialChars(enr.first_name), '')
I have to do a query SQL to search into the table below
Person
Name - Surname - Age
using Name, Surname ad Age as parameter of my query.
Since this query is generated dinamically, may happen that one of this parameters is equal to "" or null. In this case I expect that the behavior obtained is:
If Name = "", I want to search for surname and age regardless of the
name (every name).
I have found a possible solution to this problem and is to use a LIKE statement, in this way:
SELECT * ...
WHERE Surname like '%%' AND Name like '%%' AND Age like '%%'
When I put %% in the like it returns me all records of the table.
Is this correct or there is another way?
SQL offers methods for those issues.
You can easily use (Surname IS NULL OR Name = '' OR ...)
See: https://dev.mysql.com/doc/refman/5.7/en/is-null-optimization.html
Theres also a thread with almost the same question: MySQL syntax checking if parameter is null
...
Where (IsNull(#SurName, '') = '' OR #SurName = t.SurName)
AND (IsNull(#Name, '') = '' OR #Name = t.Name)
AND (IsNull(#Age, '') = '' OR #Age = t.Age)
For sql server it could look something like this:
select *
from t
where (
Surname like '%'+#Surname+'%'
or coalesce(#Surname,'') = ''
)
and (
Name like '%'+#Name+'%'
or coalesce(#Name,'') = ''
)
and (
Age like '%'+#Age+'%'
or coalesce(#Age,'') = ''
)
catch-all queries
Dynamic Search Conditions - Erland Sommarskog
Catch-all queries - Gail Shaw
SELECT * ...
WHERE
IF(NAME IS NULL OR NAME='',Surname LIKE '%%' AND Age LIKE '%%', Surname LIKE '%%' AND NAME LIKE '%%' AND Age LIKE '%%');
suppose the user input
mysite.com/profile?identity=1
mysite.com/profile?identity=dinodsja
mysite.com/profile?identity=1a
getting the value
$identity = $_GET['identity']; // identity can be user_id or user_name
and i have a simple select query:
SELECT * FROM lb_users WHERE (user_id = 'dinodsja' OR user_name = 'dinodsja') AND user_status = 1
and it works fine. but the problem is:
SELECT * FROM lb_users WHERE (user_id = '1a' OR user_name = '1a') AND user_status = 1
when I execute this query it also returns the result without satisfying the condition.
Table structure:
user_id bigint(25)
user_name varchar(50) utf8_general_ci
**
-> Is this a MySQL Bug ?
-> How can we avoid this ?
-> What will be the query ?
**
The reason for that is because the data type of the column user_ID is integer.
MySQL silently drops any trailing NON-Number (and anything that follows within) in the value and that is why 1a is equal to 1 since a will be remove in the value.
SQLFiddle Demo
I do remember having a similar problem long ago.
First some background: This is not a bug. It is actually a feature. Ok, it's one that might lead to such unexpected behaviour, but MySQL is thereby very tolerant w.r.t. user inputs, respective select queries:
mysql> SELECT 'a' = 'a ';
-> 1
mysql> SELECT 'A' = 'a';
-> 1
Therefore, with implicit type conversion, the result of, e.g, '1a' in INTEGER is 1, but also:
mysql> SELECT 0 = 'x6';
-> 1
mysql> SELECT 1 = ' 1';
-> 1
mysql> SELECT 1 = ' 1a';
-> 1
This feature is also implemented in other not statically typed languages. PHP, for instance, calls this type juggling. See the PHP String conversion rules and this example from the documentation:
<?php
$foo = "0"; // $foo is string (ASCII 48)
$foo += 2; // $foo is now an integer (2)
$foo = $foo + 1.3; // $foo is now a float (3.3)
$foo = 5 + "10 Little Piggies"; // $foo is integer (15)
$foo = 5 + "10 Small Pigs"; // $foo is integer (15)
?>
See JavaScript:
<script>
document.write(parseInt("40 years") + "<br>");
</script>
=> 40
Nevertheless, the solution to your problem is pretty easy: Just cast the integer to a char and do the comparison then:
mysql> SELECT * FROM lb_users WHERE (CAST(user_id AS CHAR) = '1' OR user_name = '1')
-> 1
mysql> SELECT * FROM lb_users WHERE (CAST(user_id AS CHAR) = '1a' OR user_name = '1a')
-> 0
mysql> SELECT * FROM lb_users WHERE (CAST(user_id AS CHAR) = 'dinodsja' OR user_name = 'dinodsja')
-> 1
I made a fiddle for everyone to try it out: http://sqlfiddle.com/#!2/c2835/14/0
Hope that helps,
-Hannes
According to your previous message
its a user input for profile. user can provide user_id or user_name.
so the input is valid. but no data. – DBK Mar 30 at 6:42
I'd recommend testing to see if its an integer and only search the user ID if it's an integer. It's really more of a workaround for mySQL not handling a STRING to INT comparison, but it should work.
declare #InputVar varchar(10)
set #InputVar = '1a'
SELECT *
FROM lb_users
WHERE
(case when isnumeric(#InputVar) = 1 then
case when (user_id = #InputVar OR user_name = #InputVar) then 1 else 0 end
else
case when user_name = #InputVar then 1 else 0 end
end =1 )
And
user_status = 1
When dealing with strings I would use 'LIKE' instead of '=' to avoid this silent type conversion madness. LIKE is made to work with strings so why not use it.
SELECT * FROM lb_users WHERE (user_id = '1a' OR user_name = '1a') AND user_status = 1
you get 1 result if you change '1a' to 1a you get this:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1a LIMIT 0, 30' at line 1
This is not a bug, take a look at http://dev.mysql.com/doc/refman/5.0/en/where-optimizations.html
hope this helps
I think you cannot duplicate a primary key and an ID, I test that one and i come up with a running data..did you set the user_id with its attributes like:
user_id bigint(50) auto_increment primary key
this is not a mysql error.
I want to look for duplicate members in the database.
First I want to check if their username exists.
If not, I want to check their first name, last name and email address.
Lastly if that doesn't match anyone, I want to just check if a first name and last name exists.
I've been looking at IF/ELSE statements and even CASE in Google but I can't seem to figure out how it would work in my situation.
Here's some code that in my mind makes sense (being a PHP programmer) but it isn't how MySQL does things...
SELECT id FROM members WHERE (
IF (member_username = 'john.doe')
ELSEIF (member_firstname = 'John' AND member_lastname = 'Doe' AND member_email = 'john#doe.com')
ELSE (member_firstname = 'John' AND member_lastname = 'Doe')
) AND deleted = 0
How would I translate the above into working MySQL code if it's even possible.
I ended up taking #Corbin's advice and used
SELECT username, first_name, last_name, email_addr FROM members WHERE username = 'username' OR (first_name = 'first name' AND last_name = 'last name')
And then used PHP if/else statements to determine which record was the exact duplicate.
What would be wrong with this?
SELECT id
FROM members
WHERE (member_username = 'john.doe'
OR (member_firstname = 'John' AND member_lastname = 'Doe' AND member_email = 'john#doe.com')
OR (member_firstname = 'John' AND member_lastname = 'Do'))
AND deleted = 0
Have a look at this: http://docs.oracle.com/cd/E17952_01/refman-5.5-en/control-flow-functions.html#operator_case
Don't forget TOP 1!
SELECT TOP 1 id FROM members WHERE deleted = 0 AND
(
(member_username = 'john.doe') OR
(member_email = 'john#doe.com' AND member_firstname = 'John' AND member_lastname = 'Doe') OR
(member_firstname = 'John' AND member_lastname = 'Doe')
)
I have a somewhat complex mySQL query I am trying to execute. I have two parameters: facility and isEnabled. Facility can have a value of "ALL" or be specific ID. isEnabled can have value of "ALL" or be 0/1.
My issue is that I need to come up with logic that can handle the following scenarios:
1) Facility = ALL AND isEnabled = ALL
2) Facility = ALL AND isEnabled = value
3) Facility = someID AND isEnabled = ALL
4) Facility = someID AND isEnabled = value
The problem is that I have several nested IF statements:
IF (Facility = 'ALL') THEN
IF (isEnabled = 'ALL') THEN
SELECT * FROM myTable
ELSE
SELECT * FROM myTable
WHERE isEnabled = value
END IF;
ELSE
IF (isEnabled = 'ALL') THEN
SELECT * FROM myTable
WHERE facility = someID
ELSE
SELECT * FROM myTable
WHERE facility = someID AND isEnabled = value
END IF;
END IF;
I would like to be able to combine the logic in the WHERE clause using either a CASE statement or Conditional's (AND/OR) but I am having trouble wrapping my head around it this morning. Currently the query is not performing as it is expected to be.
Any insight would be helpful!
Thanks
You could do this...
SELECT
*
FROM
myTable
WHERE
1=1
AND (facility = someID OR Facility = 'ALL')
AND (isEnabled = value OR isEnabled = 'ALL')
However, this yields a poor execution plan - it's trying to find one size fits all, but each combination of parameters can have different plans depending on data, indexes, etc.
This means that it is better to build the query dynamically
SELECT
*
FROM
myTable
WHERE
1=1
AND facility = someID -- Only include this line if : Facility = 'ALL'
AND isEnabled = value -- Only include this line if : isEnabled = 'ALL'
I know it can feel dirty to use dynamic queries, but this is a good corner case as to when then really can excel. I'll go find a spectacularly informative link for you now. (It's a lot to read, but it's very worth learning from)
Link : Dynamic Search