I'm fairly inexperienced in SQL and this seems like it must be an easy task, but I'm not sure how to go about it.
Basically I want to select a single row from table A where field "someField" is in a pre-determined set "someSet", but I want it to look for each value in the set individually. For example, let's say "someSet" contains 5, 6, 9, 3. I would use a query similar to this:
SELECT * FROM A WHERE someField IN (5, 6, 9, 3) LIMIT 1
However, I want it to look for 5 first, then 6, then 9, then finally 3 if no rows have been found yet. Written as separate queries it'd look like this:
SELECT * FROM A WHERE someField = 5 LIMIT 1
(if no results returned)
SELECT * FROM A WHERE someField = 6 LIMIT 1
(if no results returned)
SELECT * FROM A WHERE someField = 9 LIMIT 1
(if no results returned)
SELECT * FROM A WHERE someField = 3 LIMIT 1
Obviously using 4 queries (theoretically infinite queries) isn't very elegant, is there a way to make this into a single query?
You can do
SELECT * FROM A WHERE someField IN (5, 6, 9, 3)
ORDER BY FIELD( someField, 5, 6, 9, 3)
LIMIT 1
Related
I use mysql to deal some data use multi-thread, first I search the data use id range, like:
select id
from xxx
where id between 1 and 1000
and accountant_time = '2021-05-31 00:00:00'
and enter_accounts_state = 1
and enter_ce_state = 2
and ebs_summary_state = 2
and is_del = 0
result id like '1, 2, 3, 4, 5, ... 1001'.
and second I will delete these match data with addtional condition confirm_state from table like sql below:
DELETE
FROM xxx
WHERE confirm_state = 3
AND id IN ( 1, 2, 3, 4, ..., 1001);
All of the id range no intersection。
I found that some thread need return 1001 rows, but only returned the first row,
I tried several times use same code and same data, but the left data also not same, the common feature is only return first row of that batch count which need return all。
When I add for update for the select sql, it works normal,
How can I understand what happens?
I want to get data from table where Id should be as given below in the query but instead of or I would apply and operator so lets say ID IN (5 AND 4 AND 3)
SELECT * FROM table WHERE id IN (5,4,3,1,6)
Is it possible to get data like this.
This is the sample query
SELECT PM.ContentID, PM.Author, PM.Title, PM.Journal, PM.Year, PM.Category, PM.StudyLocation, PM.FileURL from PublishedContentMaster PM join TopicContentMapping T ON T.ContentID=PM.ContentID where PM.ContentID='100' AND T.TopicID IN (16,7)
So I want which is present in both 16 and 17 that is why I need and operator not or.
I suspect that you want an aggregation query and a having clause. It would typically look something like this:
select x
from t
where id in (5, 4, 3, 1, 6)
group by x
having count(*) = 5;
In this case, x would be the column where you want five rows with the five values.
For experimental purposes only.
I would like to build a query but not querying data extracted for any table but querying data provided in the query it self. Like:
select numbers.* from (1, 2, 3) as numbers;
or
select numbers.* from (field1 = 1, field2 = 2, field3 = 3) as numbers;
so I can do things like
select
numbers.*
from (field1 = 1, field2 = 2, field3 = 3) as numbers
where numbers.field1 > 1;
If the solution is specific for a database engine could be interesting too.
If you wanted the values to be on separate rows instead of three fields of the same row, the method is the same, just one row per value linked with a union all.
select *
from(
select 1 as FieldName union all
select 2 union all
select 3 union all
select 4 union all -- we could continue this for a long time
select 5 -- the end
) as x;
select numbers.*
from(
select 1 ,2, 3
union select 3, 4, 5
union select 6, 7, 8
union select 9, 10, 11 -- we could continue this for a long time
union select 12, 13, 14 -- the end
) as numbers;
This works with MySQL and Postgres (and most others as well).
[Edit] Use union all rather than just union as you do not need to remove duplicates from a list of constants. Give the field(s) in the first select a meaningful name. Otherwise, you can't specify a specific field later on: where x.FieldName = 3.
If you don't provide meaningful names for the fields (as in the second example), the system (at least MySQL where this was tested) will assign the name "1" for the first field, "2" as the second and so on. So, if you want to specify one of the fields, you have to write expressions like this:
where numbers.1 = 3
Use the values row constructor:
select *
from (values (1),(2),(3)) as numbers(nr);
or using a CTE.
with numbers (nr) as (
values (1),(2),(3)
)
select *
from numbers
where nr > 2;
Edit: I just noticed that you also taggeg your question with mysql: the above will not work with MySQL, only with Postgres (and a few other DBMS)
You can use a subquery without table like so:
SELECT
numbers.*
FROM (
SELECT
1 AS a,
2 AS b,
3 AS c
UNION
SELECT
4,
5,
6
) AS numbers
WHERE
numbers.a > 1
If you like queries to always have a table referenced there is a Psuedo table that always has 1 row and no columns called DUAL, you can use it like so:
SELECT
numbers.*
FROM (
SELECT
1 AS a,
2 AS b,
3 AS c
FROM
DUAL
UNION
SELECT
4,
5,
6
FROM
DUAL
) AS numbers
WHERE
numbers.a > 1
I got a array with a query
This array is ordered by criteria.
Now I want to make a new query
Sample
$array = (987, 2661, 12, 789, 54);
And I want in this order by array selecting articles
select * from article a.number WHERE (a.number IN ($array))
How can I realize that this result is ordered by $array ids?
Thx you 4 answer guys :)
edit :
Article Table:
id, name etc..
Property Table:
id, article_id, name, value
1, 10, journey_days, 2
2, 30, journey_days, 1
3, 40, journey_days, 5
1, 10, stars, 2
2, 10, stars, 4
3, 10, stars, 0
4, 10, stars, 1
I join both tables, but as you can see the property have more then one value per column for one article.
I need to join the Property table to the article table and get all Values there are related from property table to the article, if I make a where clause I just get stars or journey_days.
How can I realise this? to select all property.name values with a where or on clause?
Hope you guys understand my question
Use implode:
$s = implode(",", $array);
$q = "select * from article a.number WHERE (a.number IN ($s))";
You could construct a CASE expression and order by that, but it's probably better to do this in PHP, outside of the database.
... ORDER BY CASE a.number
WHEN 987 THEN 1
WHEN 2661 THEN 2
WHEN 12 THEN 3
WHEN 789 THEN 4
WHEN 54 THEN 5
END;
Or you could use the FIND_IN_SET function:
.... ORDER BY FIND_IN_SET(a.number, "987,2661,12,789,54");
I am going to have a fixed list of items to order by that I won't know until I run the query since there is a randomization step.
I would like to have something like the following:
Assume that is_launch_set will return 1, 3, 7, 11 but have been randomized to below:
SELECT * FROM items WHERE is_launch_set=1 ORDER BY id values (3,11,7,1);
Any ideas on how to achieve this? I was thinking maybe a find_in_set but not really sure.
You can do that by using either:
ORDER BY FIND_IN_SET(id, '3,11,7,1')
or
ORDER BY FIELD(id, 3, 11, 7, 1)
or
ORDER BY CASE id WHEN 3 THEN 0
WHEN 11 THEN 1
WHEN 7 THEN 2
WHEN 1 THEN 3
ELSE 4
END
In mys sql 8.0 it order only by the first column - 3 in this case:
ORDER BY FIND_IN_SET(id, '3,11,7,1')
With this example it worked, but upside. you'll see the 3 last, then 11, then 7 etc.
ORDER BY FIELD(id, 3, 11, 7, 1)
If you chose this example, you'll see the 1 first, then 7, then 11 etc.
ORDER BY FIELD(id, 3, 11, 7, 1) DESC