How to run alternative where condition if row is zero - mysql

Suppose i have a table
table
+-------------+
| id | name |
+-------------+
| 1 | xabx |
| 2 | abxd |
| 3 | axcd |
| 4 | azyx |
| 5 | atyl |
| 6 | aksd |
| 7 | baabc|
| 8 | aabcd|
+-------------+
first i have to get data if matches first some char like :
if name = aab
then have to run select * from table where name like 'aab%'
then it returns
+-------------+
| 8 | aabcd |
+-------------+
which execatlly i want
but if i have only abc
then the above query return 0 row
then i have to search from middle like :
select * from table where name like '%abc%'
then it returns which is the alternative
+-------------+
| 7 | baabc|
| 8 | aabcd|
+-------------+
i have no much knowledge about mysql is there any query which can do like if first where condition don't have row then run alternative where condition
i have tried this but didn't work as i want.
select * from table where name like 'abc%' or name like '%abc%'
fiddle
thanks in advance

This is somewhat your desired result:
select *from t
where (case
when name like 'abc' then 1
when name like 'bc%' then 1
when name like '%bc' then 1
when name like '%bc%' then 1
else null
end)
order by name
limit 1;
I just put all the combinations as conditions.
You can interchange their sequence or remove unnecessary condition.
limit 1 makes only 1 row visible for whichever condition satisfies.
Here is the answer from your fiddle. Check it out
Hope it helps!

This is a possible solution:
Left joining the table on itself, where the table is initially filtered by the more inclusive %bx% and then the join is filtered by the more restrictive bx%.
This allows you to use the joined name if it exists, but revert to the original if not:
SELECT t1.id, IF(t2.name IS NULL, t1.name, t2.name) name
FROM test t1
LEFT JOIN test t2 ON t2.id = t1.id AND t1.name like 'bx%'
WHERE t1.name LIKE '%bx%'
This may/may not be ideal depending on the size or your dataset.

COUNT checking may work
select *
from table
where name like 'aab%' or
((select count(*) from table where name like 'aab%') = 0 and name like '%abc%')
I guess that it would be a good idea to compute the count value into a variable first, however, the optimizer may recognize independent subquery anyway and run it once.

Related

How to select both sum value of all rows and values in some specific rows?

I have a record table and its comment table, like:
| commentId | relatedRecordId | isRead |
|-----------+-----------------+--------|
| 1 | 1 | TRUE |
| 2 | 1 | FALSE |
| 3 | 1 | FALSE |
Now I want to select newCommentCount and allCommentCount as a server response to the browser. Is there any way to select these two fields in one SQL?
I've tried this:
SELECT `isRead`, count(*) AS cnt FROM comment WHERE relatedRecordId=1 GROUP BY `isRead`
| isRead | cnt |
| FALSE | 2 |
| TRUE | 1 |
But, I have to use a special data structure to map it and sum the cnt fields in two rows to get allCommentCount by using an upper-layer programming language. I want to know if I could get the following format of data by SQL only and in one step:
| newCommentCount | allCommentCount |
|-----------------+-----------------|
| 2 | 3 |
I don't even know how to describe the question. So I got no any search result in Google and Stackoverflow. (Because of My poor English, maybe)
Use conditional aggregation:
SELECT SUM(NOT isRead) AS newCommentCount, COUNT(*) AS allCommentCount
FROM comment
WHERE relatedRecordId = 1;
if I under stand you want show sum of newComments Count and all comments so you can do it like
SELECT SUM ( CASE WHEN isRead=false THEN 1 ELSE 0 END ) AS newComment,
Count(*) AS AllComments From comments where relatedRecord=1
also you can make store procedure for it.
To place two result sets horizontally, you can as simple as use a subquery for an expression in the SELECT CLAUSE as long as the number of rows from the result sets match:
select (select count(*) from c_table where isread=false and relatedRecordId=1 ) as newCommentCount,
count(*) as allCommentCount
from c_table where relatedRecordId=1;

select statement from 2 unrelated tables

There's 2 unconnected tables, with no common IDs
+---------------------+
| names |
+------+--------------+
| name | lastN |
+-------------+-------+
| Anthony | monta |
| Ryo | shizu |
+------+--------------+
+----------------------+
| nicknames |
+------+---------------+
| nickname |
+------+---------------+
| miso_hungry |
+------+---------------+
I'm trying to run a select query on both tables and currently doing something like:
SELECT names.name, nicknames.nickname
FROM names, nicknames
WHERE names.name="miso_hungry" OR nicknames.nickname="miso_hungry"
I'm getting back a weird results with repeating identical rows, which doesn't make sense.
For example if I search for miso_hungry with the query above it will return every row of "names" table for some reason and append the correct rows from the "nicknames" table..
Attaching a screenshot of the results
Above should show "NULL" under name column, since "miso_hungry" is not found in that column and I'm not sure why it prints every row of the "names" table also.
You can use UNION Clause
Each SELECT statement within UNION must have the same number of columns
The columns must also have similar data types
The columns in each SELECT statement must also be in the same order
So we need to made them satisfy above condition. We can use Aliasing to do this.
SELECT name,(SELECT NULL) as nickname FROM names WHERE name = "miso_hungry"
UNION
SELECT (SELECT NULL) as name, nickname FROM nicknames WHERE nickname = "miso_hungry"
Edited
If you want to get the match count from both table use query like below :
SELECT SUM(count) as count FROM (
SELECT count(*) as count FROM names WHERE name = "miso_hungry"
UNION ALL
SELECT count(*) as count FROM nicknames WHERE nickname = "miso_hungry"
) both_table
The order of execution in your statement is from,where,select. With and implicit join you get a cartesian product which given
use sandbox;
create table n(name varchar(20));
create table nn(nickname varchar(20));
insert into n values('Antony'),('Ryo');
insert into nn values('miso');
results in
MariaDB [sandbox]> SELECT n.name, nn.nickname
-> FROM n, nn;
+--------+----------+
| name | nickname |
+--------+----------+
| Antony | miso |
| Ryo | miso |
+--------+----------+
2 rows in set (0.00 sec)
The where clause is then applied - which yields the same result.

Retrieve rows in which a column doesn't contain a value

I have a MySQL table like below:
| ID | userIDs
---------------
| 1 | 4,3,5
| 2 | 2,3
| 3 | 1,2,3
I want to retrieve all the rows in which userIDs doesn't contain 1.
I tried
SELECT * FROM tablename WHERE 1 NOT IN (userIDs)
But it's not working.
Use FIND_IN_SET
SELECT * FROM tablename
WHERE find_in_set(1, userIDs) = 0
But actually you should rather change your table design. Never store multiple values in a single column!

Mysql select IN return null if id not exists

I have a table like this:
+----+---------+---------+
| Id | column1 | column2 |
+----+---------+---------+
| 1 | a | b |
| 2 | a | b |
+----+---------+---------+
and a query like this SELECT * FROM table WHERE id IN (1,2,3)
what query do I need to get a result like this(I need to get null values for nonexisten id's):
+----+---------+---------+
| Id | column1 | column2 |
+----+---------+---------+
| 1 | a | b |
| 2 | a | b |
| 3 | null | null |
+----+---------+---------+
EDIT
Thanks for the responses so far.
Is there a more 'dynamic way' to do this, the query above it's just an example.
In reality I need to check around 1000 id's!
You could use something like this:
SELECT ids.ID, your_table.column1, your_table.column2
FROM
(SELECT 1 as ID
UNION ALL SELECT 2
UNION ALL SELECT 3) ids left join your_table
on ids.ID = your_table.ID
First subquery returns each value you need in a different row. Then you can try to join each row with your_table. If you use a left join, all values from the first subquery are shown, and if there's a match with your_table, values from your_table are shown, otherwise you will get nulls.
That is not the way SQL works unfortunately. I would think it would be pretty trivial for your application to determine the differences between the id's it asked for and the id's returned.
So rather than hack or some weird query to mock up your result, why not have your application handle it?
I still can't understand though what the use case might be to where you would be querying rows on teh database by id's that may or may not exist.

Order the rows of a MySQL result based on a "next_id" field

I'm currently working with a database table that is structured as follows:
______________________________
| id | content | next_id |
|------|-----------|-----------|
| 1 | (value) | 4 |
| 2 | (value) | 1 |
| 3 | (value) | (NULL) |
| 4 | (value) | 3 |
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
The value of the next_id field defines the id of the row of data that should follow it. A value of NULL means that no row follows it.
Is there a way I can query the database in such a way that in the resulting rows will be ordered using this method? For example, in the case I gave above, the rows should be returned ordered so that the ids are in this order: 2, 1, 4, 3. I'm looking for a solution that can do this regardless of the number of rows in this sequence.
I know that it is possible to reorder the results after retrieving them from the database (using the programming language I'm working with), but I'm hoping that there is a way that I can do it in SQL.
I can't see a solution without as many self-joins as you have rows. Instead I would build a nested set out of it in a temp table using push down stack algorithm and then retrieve a full tree.
I've got something that's close.
/*one select to init the #next variable to the first row*/
select #next:= id from table1 order by isnull(next_id) asc, next_id asc limit 1;
select distinct a.id, a.next_id from table1 b
inner join
(
select #rank:= id as id, #next:= next_id as next_id from table1
where id = #next
) a
on (b.id = b.id);
This outputs
+----+---------+
| id | next_id |
+----+---------+
| 2 | 1 |
| 1 | 4 |
And then stops. If only I could find a way for it to continue....
Anyway this sort of force feeding values into a query is dodgy enough when doing ranking, let alone this sort of stuff, so maybe I'm going down a dead end.