I am trying to understand the following snippet of a complicated MYSQL procedure, where var1, var2, var3 and var4 are declared variables:
select col1, col2, col3, col4
from table
order by col1 limit 5, 1 into var1, var2, var3, var4;
In particular, I don't know what the above is inserting into var1, var2, var3 and var4.
More generally, I don't understand what the following does in MYSQL:
select...limit ..., 1 into
Any help would be great!
Lets dissect the query.
select col1, col2, col3, col4 from table;
This gives you all the rows from the table, but only with 4 columns.
select col1, col2, col3, col4 from table order by col1;
Now you are are ordering the results in the ascending order of col1.
select col1, col2, col3, col4 from table order by col1 limit 5, 1;
Here 5 is the offset and 1 is the actual limit, which will reduce your result set to a size of 1.
What does offset mean?
Suppose you get 10 results from the second query. Then this third query will give you results starting from the 6th row and limited by the limit passed, which in this case is 1. Hence, you will only get one row having four values.
What does into do?
It simply stores the values of those 4 results into those 4 variables.
So LIMIT can take two paramaters LIMIT offset, count
offset is the offset of the first row you want to return (for example offset of row 1 would be 0)
count is the max amount of rows that you want to return
If you pass it just one parameter then that's just a count so LIMIT 5 would return the first 5 rows in the table.
so your query is returning the 4 values of col1, col2, col3 and col4 that are in row 6 and then is returning those values into var1, var2, var3, var4
(I think... I haven't used anything like that in a while... so I stand to be corrected)
Related
I have a query in which IN operator is used but that query is very slow in production environment.
This is my query
SELECT col1 FROM table_name WHERE col2 IN (251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,
270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,1,2,3,4,5,6,7,8,9,10,11,12,13,14) AND col3 > '1' AND col4 = 1 GROUP BY col1;
I tried find in set but still it is slow, I used composite indexing with the same order of columns as I wrote in where clause, its query cost 151630.44, filter 100 and table contain million of records.
I am expecting to get its query cost as small as possible that is, 1 or 2 and filter 100.
In tends to be slower than comparison. Seeing that your values appear to be largely sequential, try something like
SELECT col1
FROM table_name
WHERE ((col2 >=1 AND Col2 <=14) or (Col2 >=251 AND Col2 <=298))
AND col3 > '1' AND col4 = 1
GROUP BY col1;
I am looking to get a sequence of values by combining two columns that are linked using some random ids:
Table (col2 and col3 are linked)
col1 col2 col3
aa a144 d653
bb z567 a144
cc d653 h999
dd y678 z567
The two columns (col2 and col3), this is like a chain that is forming up.
The result I am looking for is a sequence from start to end:
sequence
y678
z567
a144
d653
h999
Explanation:
The sequence starts at row 4 (dd,y678,z567), followed by row 2 (bb,z567,a144) and so on.
Col3 id is the reference for the Col2 id, to decide the next element.
What you're looking for is a recursive query.
Assuming your table is called data, you do it like this:
WITH RECURSIVE query(id) AS (
SELECT col2
FROM data
WHERE col1 = 'dd' -- Select the initial row here
UNION ALL
SELECT data.col3
FROM data
INNER JOIN query on query.id = data.col2
)
SELECT *
FROM query;
Tested snippet available here: https://onecompiler.com/mysql/3xvj2a47v.
This syntax works in MySQL version 8 and up. If your version is lower, first thing I would recommend is to update it, if possible. If not possible, consult this answer for a workaround using MySQL 5: https://stackoverflow.com/a/33737203/2979473.
you are going to have to use a cursor..
https://www.mysqltutorial.org/mysql-cursor/
first step will be to select the value from col2 that doesn't exist in col3
then insert the value from col3 where the current variable is in col2
return the results set when the value in col3 is not found in col2
This will only work if there is one start and end value and one distinct path through the chain.
It will also be slow, because this is not how RDBMS databases are designed to work.
I think this query will work for you.
SELECT DISTINCT SEQ
FROM
(
SELECT COL2 SEQ FROM TABLE1
UNION
SELECT COL3 SEQ FROM TABLE1
) ORDER BY 1
I am having the following table say "A"
"column1" "column2"
1 arafath#gmail.com
2 ram#gmail.com;arafath#gmail.com
3 tom#gmail.com
I want to get the records with the following condition.
Condition1:
If the column value exist in the any of the row, it will retrieve the matched rows
Condition2:
If the column value doesn't match with any of the row, it wants to retrieve all the rows
Eg: column2 = "ram#gmail.com"
Output should be "row 2"
Eg: column2 = "arafath#gmail.com"
Output should be "row 1, row 2"
Eg: column2 = "xxx#gmail.com" (Unmatched column)
Output should be all the rows (row 1, row 2, row 3)
Please help me out to solve the problem.
Thanks in advance.
Please try the below one.
SELECT col1, col2
FROM yourTable
where ( not exists (Select col2
FROM yourTable where col2 like 'xxx#gmail.com')
or col2 like 'xxx#gmail.com');
We can try using a union here:
SELECT col1, col2
FROM yourTable
WHERE col2 REGEXP '[[:<:]]ram#gmail.com[[:>:]]'
UNION ALL
SELECT col1, col2
FROM yourTable
WHERE col2 NOT REGEXP '[[:<:]]ram#gmail.com[[:>:]]' AND
NOT EXISTS (SELECT 1 FROM yourTable WHERE col2 REGEXP '[[:<:]]ram#gmail.com[[:>:]]');
Demo
The above strategy is that the first half of the union returns the matching record, if it exists. The second half of the union then returns all other records, but only if on match were found in the first half of the union. If a match were found, then the WHERE clause in the second half of the union would fail, and would return nothing.
Also, please note that storing comma separated (or semicolon separated) data in your MySQL tables is generally bad practice. I had to use REGEXP to get around this problem, but ideally if each email had a separate row, we would only need to use = equality.
I'm troubled how to use HAVING clause avoiding function calling twice.
here is my qry:
select col1, col2, dbo.someFunction(param1, param2) as col3
from...
where ...
group ...
having dbo.someFunction(param1, param2) > 0
if I wrote
having col3 > 0
server sais: Invalid column name 'col3 '.
Is there a way to use HAVING in shown situation without calling function dbo.someFunction twice?
EDIT
my execution plan with having:
and without having (commented):
Select without function in select:
Are you sure it is calling it twice?
I get the same execution plan from the following two queries
select enumID
from docSVenum1
group by enumID
having COUNT(*) > 2000
select enumID, count(*) as ccount
from docSVenum1
group by enumID
having COUNT(*) > 2000
In order not to call the function twice but refer to the result that is returned in column col3 you'll need another SELECT statement around your query, like below.
SELECT col1,
col2,
col3
FROM
(SELECT col1,
col2,
dbo.someFunction(param1, param2) AS col3
FROM ...
WHERE... ) AS Result
GROUP BY ...
HAVING col3 > 0
You can't reference a column by its alias on the same "nesting level" of the SELECT, which is why you'll have to surround your initial result in another SELECT statement, from which you will be able to reference the column by its alias.
how do I use my row number as part of my where clause?
I have, let say, 25 data and I only want to get first 10 rows or get the rows from 11 to 20.
How do I use the row number? I can't execute this query below
SET #row_number:=0;
SELECT #row_number:=#row_number+1 AS row_number, col1, col2, col3
FROM table
WHERE row_number > 1 and row_number < 10;
Update: The problem is that in my where clause row_number is unknown in table
Update 2: Thanks guys! Anyway, I found this. Select where row number = rownum
You need to use OFFSET and LIMIT
Check this article
So to get rows 11 to 20 you would do
SELECT col1, col2, col3
FROM table
LIMIT 10 OFFSET 10;