In SQL if where condition does not yield result fetch other rows - mysql

I have Query like this
Select * from customers where id = 123 and name like '%tester%';
If id : 123 and name : "tester" doesn’t exist in table i should fetch other rows with name "tester" discarding condition "id". if it exists fetch row for that id and name.
Guys i know this is can be handled in program, i want this to be done in my Query, can you please STOP DOWN VOTING and give me the solution if you know!!!

You can try something like this:
SELECT *
FROM CUSTOMERS
WHERE ( ID = 123
AND NAME LIKE '%tester%' )
OR ( NAME LIKE '%tester%'
AND NOT EXISTS (SELECT *
FROM CUSTOMERS
WHERE ID = 123
AND NAME LIKE '%tester%') )
You can find a working example on SQL Fiddle.

SELECT * FROM customers WHERE (id = 123 AND name like '%tester%') OR (name LIKE '%tester%') LIMIT 1;
It should work then

I gotcha here, check it
Select * from customers where id = 3 or name like '%tester%'
order by id=3 desc limit 1;
See you will get all rows that have either id= 3 or name is like tester. From there you will order then by the boolean value (1 if true) by if they == 3. Limiting this to 1 result will get you only the best response.
Likewise if you want to get all results you could remove the limit, assume the top one is the best result. If the first results id is not = 3 then you could say that all the results are just best matches.

Related

MySQL: One statement in one table

I need help :( I have table like this...
ID|code|item|user|
01|aaaa|1111|0001|
02|bbbb|1111|0001|
03|cccc|1111|0001|
04|dddd|1111|0001|
05|aaaa|1111|0002|
06|eeee|1111|0002|
07|ffff|1111|0001|
I'm user 0002 and I know my item numer (for example 1111). I don't know other users, ids and other codes, but i have to get only 02,03,04,07 results (for this example). Any sinle and duplicated rows (for code column) with user 002 should be ignored... if you know what i mean. Any ideas how? :(
This can be done with a subquery filter
select *
from myTable
where code not in (
select code
from myTable
where user = '0002'
)
Try with:
select ID
from myTable
where user <> '0002'
group by ID, code
having count(code) = 1

How to select a dynamic number of rows with mysql

Lets say I have a table, myTable, like this:
ID1 Value ID2
1 6.5064 3
2 7.9000 3
3 9.9390 3
4 8.6585 3
What I'm trying to do is SELECT each of those Value's for a given ID2. However, the number of rows returned for Value can change. So, if ID2 = 2, only 1 row might get returned. If drID = 4, 3 rows might get returned.
The part of my query that is trying to handle this is nested, so when I run it I get a "Subquery returns more than 1 row" error. Any idea how I can select a variable number of rows in this way?
Thanks in advance!
Edit: here is what I have so far, and the commented out portion is what I expected to select those values for me, but it throws the above mentioned error:
SELECT drDateTime AS Date,
(SELECT fncName FROM functionlist
WHERE datarecord.fncID = functionlist.fncID) AS FunctionName,
(SELECT alText FROM alarmlevellist
WHERE datarecord.alID = alarmlevellist.alID) AS AlarmDescription
#(SELECT rdValue FROM rawdata
#WHERE datarecord.drID = rawdata.drID)
FROM datarecord
WHERE alID IS NOT NULL AND drSumFlag = 1;
You should show your query.
One common place this problem occurs is in where (or having) clauses. A solution to this problem is to use in rather than =, if the subquery is in the where clause. If you have something like:
where id = (select id2 . . .)
Then change it to:
where id in (select id2 . . .)
Use a join instead of a subquery. I would probably use a join for all tables but that is up to you.
SELECT drDateTime AS Date,
(SELECT fncName FROM functionlist WHERE datarecord.fncID = functionlist.fncID) AS FunctionName,
(SELECT alText FROM alarmlevellist WHERE datarecord.alID = alarmlevellist.alID) AS AlarmDescription,
rawData.drID
FROM datarecord
INNER JOIN rawdata
ON datarecord.drID = rawdata.drID)
WHERE alID IS NOT NULL AND drSumFlag = 1;

Combine Update and Select Query

I got two MySQL working fine and i'm trying to find a way to combine them into one single query.
First, it selects ID of an employee.
SELECT 'ID' FROM `employee` ORDER BY ID DESC LIMIT 1;
Let's say it returns ID 100;
Then update data of employees whose ID is 100
UPDATE 'LOG' SET `TIME_EXIT`='2013/02/22' WHERE `ID`='100';
Can i do it all in a single query?
Just add them together:
UPDATE LOG SET TIME_EXIT = '2013/02/22'
WHERE ID = (
SELECT ID
FROM employee
ORDER BY ID DESC
LIMIT
);
But based on that code currently it'll only ever update the last employee, you will need to select the correct employee by using some other identifier to ensure you have the correct one.
UPDATE LOG SET TIME_EXIT = '2013/02/22'
WHERE ID = (
SELECT ID
FROM employee
WHERE NAME = 'JOHN SMITH'
ORDER BY ID DESC
LIMIT 1
);
It's now a few months old, but maybe helps you or others finding this via google…
If you want to UPDATE a field in the same selected table use this:
UPDATE LOG SET
TIME_EXIT = '2013/02/22'
WHERE ID = (
SELECT ID
FROM (
SELECT ID
FROM LOG
WHERE whatEverYouWantToCheck = whateverYouNeed
) AS innerResult
)
So, you SELECT id from a subselect. If you try to subselect it directly, mySQL quites with your error message You can't specify target table 'log' for update in FROM clause, but this way you hide your subsubquery in a subquery and that seems to be fine. Don't forget the AS innerResult to avoid getting the error message #1248 - Every derived table must have its own alias. Also match the subsubquery field name to the subquery field name in case you do something like SELECT COUNT(*) or SELECT CONCAT('#', ID)

MySQL replace result value with another value

I have MySQL and the query is:
select name,re_type from myTable
I want to replace all values of type:
1 = student
2 = teacher
So the result should be:
name re_type
---------------
Ron Student
Mac Teacher
Not like:
name re_type
---------------
Ron 1
Mac 2
Is it possible to make a query like that so I get the desired result in MySQL ?
You can use a CASE statement
SELECT name, CASE WHEN re_type = 1 THEN 'Student' WHEN re_type = 2 THEN 'Teacher' ELSE 'Donno' END AS re_type_text
FROM myTable
You can use a joint table that will store labels for your re_type like
re_type_id re_type_label
1 student
2 teacher
And alter your query by :
select t.name,l.re_type_label
from myTable t
inner join labelsTable l
on l.re_type_id = t.re_type
I think he wants to keep IDs on re_type field, and just decoding them when extracting.
You can use CASE WHEN or ELT(), MySql equivalent to Oracle's Decode(), like explained here
, but the Best Practice is to create an external table containing re_type and re_type_description fields, so if tomorrow you'll have new values, you don't have to change all your queries.

How to find the next record after a specified one in SQL?

I'd like to use a single SQL query (in MySQL) to find the record which comes after one that I specify.
I.e., if the table has:
id, fruit
-- -----
1 apples
2 pears
3 oranges
I'd like to be able to do a query like:
SELECT * FROM table where previous_record has id=1 order by id;
(clearly that's not real SQL syntax, I'm just using pseudo-SQL to illustrate what I'm trying to achieve)
which would return:
2, pears
My current solution is just to fetch all the records, and look through them in PHP, but that's slower than I'd like. Is there a quicker way to do it?
I'd be happy with something that returned two rows -- i.e. the one with the specified value and the following row.
EDIT: Sorry, my question was badly worded. Unfortunately, my definition of "next" is not based on ID, but on alphabetical order of fruit name. Hence, my example above is wrong, and should return oranges, as it comes alphabetically next after apples. Is there a way to do the comparison on strings instead of ids?
After the question's edit and the simplification below, we can change it to
SELECT id FROM table WHERE fruit > 'apples' ORDER BY fruit LIMIT 1
SELECT * FROM table WHERE id > 1 ORDER BY id LIMIT 1
Even simpler
UPDATE:
SELECT * FROM table WHERE fruit > 'apples' ORDER BY fruit LIMIT 1
So simple, and no gymnastics required
Select * from Table
where id =
(Select Max(id) from Table
where id < #Id)
or, based on the string #fruitName = 'apples', or 'oranges' etc...
Select * from Table
where id =
(Select Max(id) from Table
where id < (Select id from Table
Where fruit = #fruitName))
I'm not familiar with the MySQL syntax, but with SQL Server you can do something with "top", for example:
SELECT TOP 1 * FROM table WHERE id > 1 ORDER BY id;
This assumes that the id field is unique. If it is not unique (say, a foreign key), you can do something similar and then join back against the same table.
Since I don't use MySQL, I am not sure of the syntax, but would imagine it to be similar.
Unless you specify a sort order, I don't believe the concepts of "previous" or "next" are available to you in SQL. You aren't guaranteed a particular order by the RDBMS by default. If you can sort by some column into ascending or descending order that's another matter.
This should work. The string 'apples' will need to be a parameter.
Fill in that parameter with a string, and this query will return the entire record for the first fruit after that item, in alphabetical order.
Unlike the LIMIT 1 approach, this should be platform-independent.
--STEP THREE: Get the full record w/the ID we found in step 2
select *
from
fruits fr
,(
--STEP TWO: Get the ID # of the name we found in step 1
select
min(vendor_id) min_id
from
fruits fr1
,(
--STEP ONE: Get the next name after "apples"
select min(name) next_name
from fruits frx
where frx.name > 'apples'
) minval
where fr1.name = minval.next_name
) x
where fr.vendor_id = x.min_id;
The equivalent to the LIMIT 1 approach in Oracle (just for reference) would be this:
select *
from
(
select *
from fruits frx
where frx.name > 'apples'
order by name
)
where rownum = 1
I don't know MySQL SQL but I still try
select n.id
from fruit n
, fruit p
where n.id = p.id + 1;
edit:
select n.id, n.fruitname
from fruits n
, fruits p
where n.id = p.id + 1;
edit two:
Jason Lepack has said that that doesn't work when there are gaps and that is true and I should read the question better.
I should have used analytics to sort the results on fruitname
select id
, fruitname
, lead(id) over (order by fruitname) id_next
, lead(fruitname) over (order by fruitname) fruitname_next
from fruits;
If you are using MS SQL Server 2008 (not sure if available for previous versions)...
In the event that you are trying to find the next record and you do not have a unique ID to reference in an applicable manner, try using ROW_NUMBER(). See this link
Depending on how savvy your T-SQL skill is, you can create row numbers based on your sorting order. Then you can find more than just the previous and next record. Utilize it in views or sub-queries to find another record relative to the current record's row number.
SELECT cur.id as id, nxt.id as nextId, prev.id as prevId FROM video as cur
LEFT JOIN video as nxt ON nxt.id > cur.id
LEFT JOIN video as prev ON prev.id < cur.id
WHERE cur.id = 12
ORDER BY prev.id DESC, nxt.id ASC
LIMIT 1
If you want the item with previous and next item this query lets you do just that.
This also allows You to have gaps in the data!
How about this:
Select * from table where id = 1 + 1