suppose I do this:
SELECT * FROM table WHERE field2 = '2019#162440' OR field2 LIKE '%%2019#%%';
In this case, it will try to execute the matching of BOTH field2 = '2019#162440'and field2 LIKE '%%2019#%%' conditions (ie, it will search for rows matching those conditions hence it takes some more computation power to try to find rows matching both condition even if it already found a row matching field2 = '2019#162440')
Is there a way to instruct mysql by reforming the query to ONLY try to execute field2 LIKE '%%2019#%%' if the condition field2 = '2019#162440' does not match anything so that the query becomes more efficient
IE. I essentially want mysql to only try to find rows matching field2 LIKE '%%2019#%%' only if no rows match field2 = '2019#162440'. If a row that matches field2 = '2019#162440' is found, do NOT try to match field2 LIKE '%%2019#%%'
Also, no subqueries
Let me start by stating that I am not an expert in MySQL. It is not nearly as optimized as some other DBMSes, so the following query might not actually reduce your execution time. But it's worth a shot...
If field2 is indexed, this might be a really fast solution:
-- Get results where field2 = '2019#162440'
SELECT *
FROM table
WHERE field2 = '2019#162440'
-- Append...
UNION
-- Get results where field2 LIKE '%%2019#%%' but only
-- if there are no rows where field2 = '2019#162440'
SELECT *
FROM table
WHERE NOT EXISTS(
SELECT *
FROM table
WHERE field2 = '2019#162440'
)
AND field2 LIKE '%%2019#%%'
You are going to run your fastest query and select all results. Then, append the second, slower query which contains an EXISTS. The EXISTS clause will return true if the subquery contains any rows, which should short-circuit the entire second query and prevent it from runnning (thus appending 0 rows). If the first query returns 0 rows, however, then the second query will kick in and run the slower LIKE comparisons.
The best I can do is use the FOUND_ROWS() function along with a UNION:
SELECT *
FROM t
WHERE field2 = '2019#162440'
UNION ALL
SELECT *
FROM t
WHERE FOUND_ROWS() = 0
AND field2 LIKE '%%2019#%%'
SQL Fiddle Demo
Related
I get data from MySQL with if statement as code below. but I get an error:
Error Code: 1241. Operand should contain 1 column(s).
so can someone can help me?
I can not put it into the procedure, because I am using spring + mybatis in the project and i will put this code into them.
SELECT IF((SELECT COUNT(*) FROM table1 WHERE someField = 'A') < 0,
(SELECT * FROM table2 WHERE someField = 'A'),
(SELECT * FROM table1 WHERE someField = 'A'))
From the comments: I wanna get data of 1 in 2 tables when table 1 don't have data I will get data from table 2.
That sounds like union all and not exists:
select * from table1 where someField = 'A'
union all
select * from table2 where not exists(select 1 from tabe1 where someField = 'A'
Note that, for this to work, both tables must contain exactly the same number of columns, whith aligned datatypes. You should really be enumerating the columns that you want to show in the resultset in both unioned queries, to avoid any possible ambiguity. If needed, you can cast columns or add litteral values to any or both of the resultset to align the resultsets (without seeing your actual data structures, I cannot tell how to do).
I have a question on HAVING statement in SQL.
Is a query like this possible?
SELECT COUNT(T.IDtif) AS NumeroTifosi
FROM Tifosi T, Partita P
WHERE T.IDtif=P.Tifoso AND P.Partita=P.Idpar
HAVING COUNT(P.Idpar) = ( SELECT COUNT(Idpar) FROM Partita
WHERE Data BETWEEN “2002101” AND ”20021231”)
I don't understand if it is possible to compare an aggregation function, in a HAVING statement, with a subquery that returns a single value.
That's what the parentheses do. You can compare a single result of a SELECT by turning telling SQL "it's ok, this has one value".
It could be:
SELECT ColA = (SELECT ColB from TableB Where Id = 1)
FROM TableA
or
SELECT *
FROM TableA
WHERE ColA = (SELECT ColB from TableB Where Id = 1)
or even with HAVING as you describe.
Yes. This query if perfectly valid. Are you getting an error when you try to run it?
What you are doing is running a subquery once to return a count. Then for each group, you are checking if the number of rows in that group is equal to the number returned by the subquery.
I have a simple query that selects one field and only one row, thus one value.
Is there any way to make it return NULL if the query results in an empty set? Instead of returning zero rows?
I think I need to use something with NOT EXISTS, THEN NULL but not certain about it.
select
(Your entire current Select statement goes here) as Alias
from
dual
dual is a built in table with a single row that can be used for purposes like this. In Oracle this is mandatory. MySQL supports it, but you can also just select a single value without specifying a table, like so:
select
(Your entire current Select statement goes here) as Alias
In either case you're selecting a single value. This means that:
If your select returns one value, that value is returned.
If your select statement returns one column, but no rows, NULL will be returned.
If your select statement returns multiple columns and/or multiple rows, this won't work and the query fails.
An easy way to do this is with aggregation:
select max(col)
from t
where <your condition here>
This always returns one row. If there is no match, it returns NULL.
Late reply but I think this is the easiest method:
SELECT
IFNULL((SELECT your query), NULL)
Use a UNION with a NOT EXISTS(original where clause)
select col1
from mytable
where <some condition>
union
select null
where not exists (
select * from mytable
where <some condition>)
You can use COALESCE for example:
SELECT COALESCE(Field1,NULL) AS Field1 FROM Table1
Edit 1:
sorry i mistake with return field as null not result set,for result set return as null use Union and Exist Function like this:
SELECT NULL AS Field1 FROM Table1 WHERE not EXISTS(SELECT Field1 FROM Table1 WHERE Field2>0)
UNION
SELECT Field1 FROM Table1 WHERE Field2>0
I need a query in which it starts off by selecting the entire table, then there would be a few more querys that would remove entries from the first query. Ive accomplished this by using several querys and then comparing the results in my application. I was wondering if I can accomplish this in a single query.
Algorithm
Select All AccountIDs from table
Select AccountIDs from table where parameter1 = true
Remove those matches from the original query result
Select AccountIDs from table where parameter2 = true
Remove those matches from the remaining query result
and so on up to N parameters.
This would need to also be compatible with both mySQL and SQLite
I think you are looking for this:
SELECT AccountID FROM the_table
LEFT JOIN (
SELECT AccountID FROM the_table
WHERE
parameter1 = true OR
... OR
parameterN = true ;
) AS not_included USING (AccountID)
WHERE not_included.AccountID IS NULL -- only items with no match in the "not_included" sub-query
The not_included subquery returns all items for which any parameter is set to TRUE. You actually want to exclude these records from your final result set.
Then LEFT-JOIN the_table (i.e. all items) to this sub-result. The WHERE...IS NULL clause excludes items present in the_table but not present in not_included.
Therefore only items which you do not want to exclude remain in the final result set.
The most direct way to implement your algorithm is to use a compound SELECT statement:
SELECT AccountID FROM MyTable
EXCEPT
SELECT AccountID FROM MyTable WHERE parameter1 = 1
EXCEPT
SELECT AccountID FROM MyTable WHERE parameter2 = 1
However, this is also possible with a single WHERE expression:
SELECT AccountID
FROM MyTable
WHERE NOT (parameter1 = 1 OR
parameter2 = 1 OR
...)
I have the following query working:
SELECT DISTINCT table1.field1, table1.field2
FROM table1
WHERE table1.field3 IN (1,2,3)
Result:
field1 field2
Data1 60
Data2 61
Data3 62
And the following query only gives me the first row when it should give the exact same result as the first query.
SELECT DISTINCT table1.field1, table1.field2
FROM table1
WHERE table1.field3 IN (SELECT table2.field1 FROM table2 WHERE table2.field2 = 100)
Result:
field1 field2
Data1 60
If I execute the subquery (SELECT table2.field1 FROM table2 WHERE table2.field2 = 100), the result is "1,2,3", exactly like the first query.
What i'm I missing?
What you're missing is that a string with the value '1,2,3' is not a list of three integers. It's one string.
If you want x IN (SELECT y FROM z) to behave in the same way as x IN (1,2,3), then your sub-query must return three items, with the values 1, 2, and 3.
There are Split() functions on the web that take a string and return a record set consisting of multiple integers. And that may fix your problem.
But the fact that you have a single record with a single field holding multiple values is a sign of a deeper problem. You should never store multiple values in a relational database as a single string. Instead store multiple records, or multiple fields.