In a simple query like
SELECT *
FROM table
WHERE id='x' OR id='y'
How to give a priority to get only one of the WHERE clauses?
I mean getting rows with id='x'. Only if there is no row, get row with id='y'.
In other words, do not use id='y' if there is a row for id='x'.
If you want only one row, the simplest method is limit:
SELECT t.*
FROM table t
WHERE id IN ('x', 'y')
ORDER BY (id = 'x') DESC
LIMIT 1;
The id = 'x' in the order by uses the fact that MySQL treats boolean values as integers in a numeric constant. So "true" is treated as 1 and "false" as 0. The DESC puts the true values (i.e. 'x') first.
If there are multiple possible rows that could be returned, then NOT EXISTS is a possibility:
select t.*
from t
where t.id = 'x' or
(t.id = 'y' and
not exists (select 1 from t t2 where t2.id = 'x')
);
In MySQL, this version might be optimized better using union all, if you have an index on id:
select t.*
from t
where t.id = 'x'
union all
select t.*
from t
where t.id = 'y' and
not exists (select 1 from t t2 where t2.id = 'x');
Here is another way to fetch same data with help the Rank basis, And it's support multiple values as well as, based on your select statement.
SELECT TOP 1 *, (RANK() OVER (ORDER BY VAL DESC )) AS RANK_N FROM TEST_TABLE T WHERE T.ID IN('X','Y') ORDER BY RANK_N
You can use case statement or limit clause. Limit clause is the better option. Do not forget to use order by while using limit clause
select * from
(SELECT *
FROM table
WHERE id='x' OR id='y')
where
case when id = 'x' then id = 'x'
when id = 'Y' then id = 'Y' end ;
SELECT * FROM table WHERE id='x' OR id='y' order by id limit 1;
Related
I want to update a column in a MySQL table that contains string values with values from another table that contains unique names, but without repeating the same values.
Each name in the 'names' table has a unique id from 1 - 1001.
There are 161 names in the target table.
I tried something like this, but it fetches duplicate entries:
UPDATE table_to_update
SET name =
( SELECT name FROM `names`
WHERE id >= (SELECT FLOOR(RAND()*(SELECT MAX(id) FROM `names`)) )
LIMIT 1 ) ;
Here is one option if you are using MySQL 8+, which supports ROW_NUMBER:
UPDATE table_to_update t1
INNER JOIN
(
SELECT id, ROW_NUMBER() OVER (ORDER BY id) rn
FROM table_to_update
) t2
ON t1.id = t2.id
INNER JOIN
(
SELECT name, ROW_NUMBER() OVER (ORDER BY id) rn
FROM (SELECT name, id FROM names ORDER BY RAND() LIMIT 161) t
) t3
ON t2.rn = t3.rn
SET
t1.name = t3.name;
Note that I hard-coded the LIMIT value to be 161 in the subquery, given that you know the size of the target table. This value could be made dynamic as well, but would require more work.
I am Using the below table
The case_id for two rows. If the case Id is same then I would want to fetch the row that has Test_script_type as automation and ignore the manual. How can I achieve it with a SQL query..If there is only manual fetch the manual row. How can I achieve it with a SQL query. The Output would be like :
Help is appreciated. Thanks for your time In-advance
You could adress this with not exists:
select t.*
from mytable t
where
script_type = 'Automation'
or not exists (
select 1
from mytable t1
where
t1.case_id = t.case_id
and t1.script_name <> t.script_name
and t1.script_type = 'Automation'
)
You can also filter with a correlated subquery:
select t.*
from mytable t
where t.script_type = (
select min(t1.script_type) -- This gives priority to 'Automation' against 'Manual'
from mytable t1
where t1.case_id = t.case_id
)
SELECT t1.*
FROM `table` t1
LEFT JOIN `table` t2 ON t1.case_id = t2.case_id AND t1.script_type != t2.script_type
WHERE t1.script_type = 'automation' OR t2.case_id IS NULL
You could do something like the following:
WITH cte AS (
SELECT T1.CASE_ID, T1.SCRIPT_NAME, T1.SCRIPT_TYPE,
COUNT(T1.CASE_ID) OVER (PARTITION BY T1.CASE_ID) AS cnt
FROM table1 T1
)
SELECT cte.CASE_ID, cte.SCRIPT_NAME, cte.SCRIPT_TYPE
FROM cte
WHERE (cte.cnt > 1 AND UPPER(cte.SCRIPT_TYPE) = UPPER('AUTOMATION'))
OR cte.cnt = 1
The WITH statement adds a column counting how many times the case_id value is duplicated, which helps identify the rows you want to work with.
Here is an example of it working with the data you have provided: SQLFiddle
If you are using MSSQL Server, You may try below query -
SELECT *
FROM (SELECT CASE_ID, SCRIPT_NAME, SCRIPT_TYPE, ROW_NUMBER() OVER(PARTITION BY CASE_ID ORDER BY SCRIPT_TYPE) RN
FROM YOUR_TAB) T
WHERE RN = 1
the sql as follows come from mysql document. it is:
SELECT * FROM t1 AS t
WHERE 2 = (SELECT COUNT(*) FROM t1 WHERE t1.id = t.id);
The document say It finds all rows in table t1 containing a value that occurs twice in a given column , and doesnot explain the sql.
t1 and t is the same table, so the
count(*) in subquery == select count(*) from t
, isn't it?
count(*) in subquery == select count(*) from t
is wrong. because in mysql you can't use it like that. so you have to run it like that to get result of same id having two rows.
if you want to get count of same occurrence,
SELECT id, name, count(*) AS all_count FROM t1 GROUP BY id HAVING all_count > 1 ORDER BY all_count DESC
And also you can get values as your query like this as well,
select * from t1 where id in ( select id from t1 group by id having count(*) > 1 )
The query contains a correlated subquery in WHERE clause:
SELECT COUNT(*) FROM t1 WHERE t1.id = t.id
It is called correlated because it is related to the main query via t.id. So, this subquery counts the number of records having an id value that is equal to the current id value of the record returned by the main query.
Thus, predicate
(SELECT COUNT(*) FROM t1 WHERE t1.id = t.id) = 2
evaluates to true for any row with an id value that occurs twice in the table.
SELECT * FROM t1 AS t
WHERE 2 = (SELECT COUNT(*) FROM t1 WHERE t1.id = t.id);
This query goes through each record in t1 and then in the subquery looks into t1 again to see if in this case id is found 2 times (and only 2 times). You can do the same for any other column in t1 (or any table for that matter).
When you would like to see all values that are multiple times in the table, change WHERE 2 = by WHERE 1 <. This will also give you the values that are 3 times, 4 times, etc. in the table.
{
SELECT id,count( * )
FROM
MyTable
group by id
having count( * )>1
}
with this code, you can see the rows which repet more than one,
and you can change this query by yourself
How about using GROUP BY and HAVING:
SELECT id, count(1) as Total FROM MyTable AS t1
GROUP BY t1.id
HAVING Total = 2
I already saw a similar question here(Get minimum unused value in MySQL column) which is exactly what I want except what I need to select the minimum available number not from just a table but from rows with specific customId as well.
In case the other question gets removed or something, here is what query is needed:
In case of rows [1,2,3] the query should return 4.
In case of rows [2,3,4] the query should return 1.
In case of rows [1,3,4] the query should return 2.
In case of multiple missing rows [1,2,4,6,7] the query should return minimum missing value 3.
I tried solutions showed in the first linked question and from this one as well link(SQL - Find the lowest unused number). I tried tweaking them to include customId in WHERE clauses but the queries is too advanced and confusing for me, so it did not work. I have tried doing this:
SELECT min(unused) AS unused
FROM (
SELECT MIN(t1.id)+1 as unused
FROM yourTable AS t1
WHERE t1.customId = ? AND NOT EXISTS (SELECT * FROM yourTable AS t2 WHERE t2.customId = ?
AND t2.id = t1.id+1)
UNION
-- Special case for missing the first row
SELECT 1
FROM DUAL
WHERE customId = ? AND NOT EXISTS (SELECT * FROM yourTable WHERE id = 1)
)AS subquery
But it shows access or syntax violation error.
You can do:
select 1 + min(col)
from t
where not exists (select 1 from t t2 where t2.col = t.col + 1);
If you need to include "1", then:
select (case when min(tt.mincol) <> 1 then 1
else 1 + min(col)
end)
from t cross join
(select min(col) as mincol from t) tt
where not exists (select 1 from t t2 where t2.col = t.col + 1)
I tweaked one of the queries I found on the web until it worked... Obviously it is not neccesarily fast or perfomant but it work, so here it goes:
SELECT min(unused) AS unused FROM
( SELECT MIN(t1.group_number)+1 as unused FROM units AS t1 WHERE t1.user_id = '.$ai_id.' AND
NOT EXISTS (SELECT * FROM units AS t2 WHERE t2.user_id = '.$ai_id.' AND t2.group_number=
t1.group_number +1) UNION
-- Special case for missing the first row
SELECT 1 FROM DUAL WHERE NOT EXISTS (SELECT * FROM units WHERE group_number= 1
AND user_id = '.$ai_id.') )AS subquery
I am not sure how exactly it works, but it somehow does, I can only get the outlines...
The user_id in this case is the aforementioned customId and unit_group_number is the column used to search for missing "hole" value which will be returned as unused.
I want to run this query
select *
from table
order asc
limit N;
where N is the total number of rows minus 10.
SELECT COUNT(*) FROM (SELECT * FROM table)
returns the total as 189 so, in this case, I would want my limit to be 179
If order is not important, you can use the offset of limit:
Note, there is no actual value for 'Until End Of Table'. The MySQL Documentation suggests to use "some large number" for the second parameter.
SELECT *
FROM table1
order by ID DESC
LIMIT 10, 999999999999999
If you do want in in ascending order you can apply a different ordering afterwards:
SELECT
*
FROM
(SELECT *
FROM table1
ORDER BY ID DESC
LIMIT 10, 999999999999999) x
ORDER BY
ID ASC
Not sure if the most efficient one, but this should work if you only have one field as a primary key.
select *
from T1
where
T1.id not in (
select top(10) id
from T1
order by id desc
)
order by
id;
It will get the last rows by your order and then you can exclude by the key.
Edit:
Better yet, instead of not in, you can use a left outer join.
select
T1.*
from T1
left outer join ( select top(10) id from Enums_Tables order by id desc ) as T2
on
T1.id = T2.id
where
T2.id is null;