Is it possible in MySQL to select from a static set of integers? Given an array of integers like 1 and 2, what is the correct syntax in MySQL to do something like:
select
*
from
(values(1),(2))
Which should return one row containing the number 1 and one row containing the number 2.
In other SQL than MySQL (e.g. MSSQL) this is possible. Is there a way to do this in MySQL?
I think you mean something like this?
SELECT 1 UNION SELECT 2 UNION SELECT 3
The only way to create a virtual set in MySQL is using a subquery with UNION. The subquery in the FROM clause creates 3 rows which can be joined with another table:
SELECT foo.*
FROM (
SELECT 1 AS num UNION
SELECT 2 AS num UNION
SELECT 3 AS num
) virtual
LEFT JOIN foo ON foo.num = virtual.num
When you want to use your list of values as a condition for WHERE or ON clause, then the IN() construct may be the right way to go:
SELECT foo.* FROM foo WHERE foo.num IN (1,2,3)
sorry for my english
you can use (IN) like this
SELECT * FROM Table WHERE id IN (1,2,3....)
Related
Given 2 tables, I want to convert the multivalued row in table 1
Given 2 tables
Table A
id value
ae [1,2,4,5]
ac [1,6]
Table B
id value
ae 1
ae 2
ae 4
ae 5
ac 1
ac 6
I know I have to insert a before insert trigger on table B, but I cannot figure out the logic.
Another way to convert JSON arrays in MySQL into rows (I assume "value" column in table A is json array type). Transform Table A into Table B.
MySql >= 8.0:
First with a recursive query I get json array indexes for each json array with a length > 0 (a row per index), then I join table A with indexes query and used JSON_EXTRACT() to extract each json array value in a row.
WITH RECURSIVE indexes AS (SELECT id, 0 AS json_index FROM A WHERE JSON_LENGTH(value) > 0
UNION ALL
SELECT i.id, i.json_index + 1
FROM indexes i
INNER JOIN A ON A.id = i.id AND i.json_index < JSON_LENGTH(A.value) - 1
)
SELECT A.id, JSON_EXTRACT(A.value, CONCAT('$[', i.json_index, ']')) AS arrayValue
FROM A
INNER JOIN indexes i ON A.id = i.id;
Here's an idea:
Get the total of value need to be separated using LENGTH():
Take the first example [1,2,4,5]. There are 4 values separated by commas here. If we do LENGTH(value), we will get 9 as there are 9 characters including [ and ,. Then we do LENGTH(REPLACE(value,',','')) which we replace the commas from the values with nothing and this will give us 6. If we subtract them, we'll get 3 which we suppose to get 4 so we add +1 in the final calculation. We end up with something like this:
(LENGTH(value)-LENGTH(REPLACE(value, ',', '' )))+1
With that, you'll get ae with 4 and ac with 2. From here there are three usage of this information:
To make a numbering sequence referring to the largest number we get, in this case 4.
To return repeated row based on how many length the value column has.
To be used in SUBSTRING_INDEX() function and return the value accordingly.
In the end, I've managed to create two queries using the same idea but for a different MySQL version.
For older MySQL version (before v8), this might do:
SELECT id,
SUBSTRING_INDEX(SUBSTRING_INDEX(val,',',ln),',',-1) AS value
FROM
(SELECT 1 AS ln UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) RN
LEFT JOIN
(SELECT id,
REPLACE(REPLACE(value,'[',''),']','') AS val
FROM tableA) A
ON ln<=(LENGTH(val)-LENGTH(REPLACE(val,',','')))+1
ORDER BY id, value;
However, the issue here is that the hardcoded numbering sequence by rows on this part of the query ..(SELECT 1 AS ln UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) RN... Meaning that if there's a value where the length is everchanging, then this part need to be constantly edited.
For MySQL v8 (but not quite v8.0.4 that supports JSON_TABLE):
WITH RECURSIVE cte AS (
SELECT 1 AS ln, MAX((length(value)-length(replace(value,',','')))+1) AS totval
from tableA UNION ALL
SELECT ln+1, totval FROM cte WHERE ln+1 <= totval)
SELECT id,
REGEXP_REPLACE(SUBSTRING_INDEX(SUBSTRING_INDEX(value,',',ln),',',-1),'[^0-9]','') AS value
FROM cte
LEFT JOIN tableA
ON ln<=(length(value)-length(replace(value,',','')))+1
ORDER BY id, value;
Here I'm using WITH RECURSIVE function to dynamically generate the numbering sequence, which means that if the length is more than 4, there's no need to edit the query.
Demo fiddle
What i want to get?
Get id,name,email of the people who have sent me friend_requests.
Two tables i have used on the basis of which i want to get the details
signup -> id,name,email,firmname and a few more columns.
friends_requests ->id,userId,sentRequests,receivedRequests,friends,dates
Please refer to the below two images.
friends requests table
Signup table
What I am trying?
SELECT * FROM signup WHERE signup.id IN
(SELECT sentRequests FROM friends_request WHERE friends_request.userId=46)
This query only gives one record, whereas if i use below query it gives 3 records
SELECT * FROM signup WHERE signup.id IN (47,48,49)
I know why second query is giving three records because of the IN clause and three id's
But this query will also give the same result which is 47,48,49
SELECT sentRequests FROM friends_request WHERE friends_request.userId=46
But why isn't the first query giving three records?
When both the values are same? Then why isn't the result same?
About table friends_requests. Column sentRequests violates 1NF.
if I am right, IN operator gets your information as full string, not as separate ID information.
SELECT *
FROM signup
WHERE signup.id IN ('47,48,49')
what is operator thinks IN ('47,48,49')
what You think IN (47,48,49)
You have to split column value '47,48,49' into returning rows so operator could understand, if you want to use IN operator...
For it to work like you coded it,
SELECT sentRequests FROM friends_request WHERE friends_request.userId=46
would have to give 3 rows with 47,48,49.
Because sentRequests is a string it gives one row with 47,48,49
If you want the 3 values go with:
select * from #signup a where exists (select 1 from friends_request b where ','+sentRequests+',' like ',%'+cast(id as varchar(5))+',%')
try this...
SELECT * FROM signup WHERE id IN (
SELECT
DISTINCT cast(SUBSTRING_INDEX(SUBSTRING_INDEX(sentRequests, ',', n.digit+1), ',', -1) AS signed) sentRequests
FROM friends_request INNER JOIN (
SELECT
0 digit
UNION ALL
SELECT 1
UNION ALL
SELECT 2
UNION ALL
SELECT 3
UNION ALL
SELECT 4
UNION ALL
SELECT 5
UNION ALL
SELECT 6
) n ON LENGTH(REPLACE(sentRequests, ',' , '')) <= LENGTH(sentRequests)-n.digit
WHERE userId = 46
);
I run a SQL query like below in MySQL:
select *
from (
select 2 as o,1 as t from dual
union
select 1 as o,2 as t from dual
) x
order by if((select 1),o,t);
It works well, but when I use column relative position in if statement, it doesn't work.
How can I use column relative position in if in ORDER BY statement?
select *
from (
select 2 as o,1 as t from dual
union
select 1 as o,2 as t from dual
) x
order by if((select 0),1,2);
I'm not sure what your real confusion is. When an integer appears in an order by, then this is treated as a column number. Any other use of an integer is interpreted as an expression.
The use of column numbers has been removed from the SQL standard. Hence, its use in any particular database is not guaranteed in future releases. It is really better to use the column names.
I think you want to sort your query based on a criteria over two columns, if I'm correct, you can use something like this:
...
order by
case when (your criteria)
then column1
else column2
end;
Note: use union all instead union when you don't want to remove duplicate values as performance issue ;).
Is it possible to join Two queries of mysql in a query ??
Like:
select * from a + select * from b
So that I can use them in a single php loop.
If they have the same number of columns and the datatypes are the same in each column, then you can use a UNION or UNION ALL:
select *
from a
UNION ALL
select *
from b
If you provide more details about the tables, data, etc, then there might be another way of returning this data.
A UNION will return only the DISTINCT values, while a UNION ALL selects all values.
If this is the route that you need to take, and you still need to identify which table the data came from, then you can always create a column to identify which table the data is from , similar to this:
select *, 'a' TableName
from a
UNION ALL
select *, 'b' TableName
from b
This allows you to distinguish what table the data came from.
I think it is easier creating sql "variables" like:
select varA, varb from TableA, tableB;
and you can just play with values in PHP accessing properties.
That way you can take conditions in the query like:
select varA, varb from TableA, tableB where varA.id = varB.foreingId bla bla...
;)
SELECT current_raised,segment FROM gizmos
where created_at >= "2012-03-01"
returns 600+ rows
SELECT "current_raised","segment"
UNION
(SELECT current_raised,segment FROM gizmos
where created_at >= "2012-03-01")
returns 180 rows
Why is this happening?
union will remove from the result set every duplicated current_raised, segment pair. Try union all instead.
Here is a reduced example of what is happening.
It's a slightly confusing feature of standard SQL: the default qualifier for SELECT is SELECT ALL but the default qualifier for UNION is UNION DISTINCT.
Your first query is implicitly using SELECT ALL and is returning duplicate rows in the result, not good. Correct the first query by explicitly using SELECT DISTINCT.