MySql update not recognizing temporary table - mysql

I have the following query script that is resulting in an error:
SET #row_number = 0;
Drop Table If Exists testtable2;
Create Temporary Table testtable2
SELECT
*
FROM
(SELECT
row_names, (#row_number:=#row_number + 1) AS num, date_add(date_time, INTERVAL 1 MINUTE) AS date_time, meter, kw
FROM
testtable
WHERE
DAY(date_time) = 1
AND HOUR(date_time) = 2) AS testtable2
WHERE
MOD(testtable2.num, 2) = 0;
UPDATE testtable
SET
testtable.date_time = testtable2.date_time
WHERE
testtable.row_names = testtable2.row_names;
The error says Error Code: 1054. Unknown column 'testtable2.row_names' in 'where clause'
I created a temporary table that contains the column date_time but my update query fails to recognize that the column exists. I can run something like SELECT * FROM testtable2; and it returns showing that the column is indeed generated with the correct title. Why can my update not recognize this column?

This is your update statement:
UPDATE testtable
SET testtable.date_time = testtable2.date_time
WHERE testtable.row_names = testtable2.row_names;
What is testtable? You have not defined that. You created testtable2. If you do have testtable, then perhaps you want a join:
UPDATE testtable tt JOIN
testtable2 tt2
ON tt.row_names = tt2.row_names
SET tt.date_time = tt2.date_time;

You actually meant to use CREATE TABLE ... AS construct but in your case it's wrongly formed. It should be like below.
Create Temporary Table testtable2 AS
SELECT
*
FROM
(SELECT
row_names, (#row_number:=#row_number + 1) AS num,
date_add(date_time, INTERVAL 1 MINUTE) AS date_time,
meter,
kw
FROM
testtable
WHERE
DAY(date_time) = 1
AND HOUR(date_time) = 2) AS XXX <-- Here
WHERE
MOD(testtable2.num, 2) = 0;
Issue in your case is, your Temporary table and inline view alias are same. name them differently. See edited query.
You can directly JOIN with the inner query and can perform UPDATE like
UPDATE testtable
JOIN (
SELECT
*
FROM
(SELECT
row_names, (#row_number:=#row_number + 1) AS num, date_add(date_time, INTERVAL 1 MINUTE) AS date_time, meter, kw
FROM
testtable
WHERE
DAY(date_time) = 1
AND HOUR(date_time) = 2) AS testtable2
WHERE
MOD(testtable2.num, 2) = 0 ) xx ON testtable.row_names = xx.row_names
SET
testtable.date_time = xx.date_time;

Related

Generate random numbers in MySQL without repeat

I have a stored procedure that insert data related to a scooter rent, one of the fields is a "rent code" when i insert the information "rent code" should be a unique random number that don exist in the table "rents"
here is that i tried
SELECT FLOOR(RAND() *9999)+1 AS random_num
FROM reservaciones
WHERE "random_num" NOT IN (SELECT reservaciones.Codigo_Reservacion FROM reservaciones)
LIMIT 1
in the table i got
1
2
3
when i run the code if i reduce the limit to 4 (example) the query still generates the numbers that i already got in my table
Create and use user-defined function similar to:
CREATE FUNCTION generate_random_number (upper_limit INT)
RETURNS INT
BEGIN
IF upper_limit = (SELECT COUNT(*) FROM main_table WHERE id <= upper_limit) THEN
RETURN NULL;
END IF;
IF upper_limit IS NULL THEN
SELECT REPEAT('9', LENGTH(MAX(id) + 1)) FROM main_table INTO upper_limit;
END IF;
RETURN (SELECT t1.id + 1
FROM (SELECT id FROM main_table
UNION ALL
SELECT 0) t1
LEFT JOIN main_table t2 ON t1.id = t2.id - 1
WHERE t2.id IS NULL
AND t1.id < upper_limit
ORDER BY RAND() LIMIT 1);
END
upper_limit parameter specifies the range from which the number should be generated. Can be less than max. existing value. Cannot be greater than 2147483647. Cannot be set to NULL if max. existing value is 999999999 or greater (you may expand this limit by set the parameter and output datatypes to BIGINT).
Function returns NULL if there is no free number in specified range.
fiddle with some comments.

Convert MySQL syntax to PostgreSQL

I use this code in MySQL to order by 'anotherColumn' and then get the row number of 'myColumn' and then I perform a calculation and set 'myColumn' to the result:
SET #c = (SELECT COUNT(*) FROM myTable); SET #rownum = 0; UPDATE myTable SET myColumn = #c * (#rownum:= 1 + #rownum) ORDER BY anotherColumn DESC LIMIT 100000;
I'm trying to achieve the same thing in Postgresql but am getting a lot of errors. I have:
SET c = (SELECT COUNT(*) FROM myTable); SET rownum = 0; UPDATE myTable SET myColumn = c * (rownum:= 1 + rownum) ORDER BY anotherColumn DESC LIMIT 100000;
.. but it gives me an error at the first parenthesis. If I remove those parenthesis like this:
SET c = SELECT COUNT(*) FROM myTable; SET rownum = 0; UPDATE myTable SET myColumn = c * (rownum:= 1 + rownum) ORDER BY anotherColumn DESC LIMIT 100000;
.. then it gives me an error at the SELECT. If I just set c to equal 0, I get an error way down at the ORDER. Does anyone know how to convert my code from MySQL to PostgreSQL?
This "pattern" in MySQL is typically used to work around the absence of window function.
You don't need variables in Postgres to achieve something like that:
update my_table
set my_column = t.cnt + t.rn
from (
select pk_column,
(select count(*) from my_table) as cnt,
row_number() over (order by another_column) as rn
from my_table
limit 100000
) t
where t.pk_column = my_table.pk_column;
Where pk_column is the primary key column of your table. If you have more than one PK column, you need to use all of them.

MySql CASE Execute Query Returns Operand should contain 1 columns

The following code returns Operand should contain 1 columns.
SELECT
CASE WHEN
(SELECT COUNT(1) FROM `student` WHERE `join_date` > '2017-03-21 09:00:00') > 0
THEN
(SELECT * FROM `student` >= CAST(CAST('2017-03-21 09:00:00' AS DATE) AS DATETIME)
END
but the following works. Why?
SELECT
CASE WHEN
(SELECT COUNT(1) FROM `student` WHERE `join_date` > '2017-03-21 00:00:00') > 0
THEN
(SELECT `foo`)
ELSE
(SELECT `bar`)
END
How if i want to perform checking and execute 2 different queries according to the checking result.
I want to achieve following result (works fine in sql)
IF (SELECT COUNT(*) FROM table WHERE term LIKE "term") > 4000
EXECUTE (SELECT * FROM table1)
ELSE
EXECUTE (SELECT * FROM table2)
If you force your subselect tor return only a row the also the first select work
SELECT
CASE WHEN
(SELECT COUNT(1) FROM `student` WHERE `join_date` > '2017-03-21 00:00:00') > 0
THEN
(SELECT * FROM `student` order by your_column limit 1)
ELSE
(SELECT * FROM `teacher` order by your_column limit 1)
END
you should also add proper order by on the column your need (in the sample named your_column ) for obtain the valid first row
You can select from both tables using UNION ALL and excluding conditions.
SELECT * FROM `student`
WHERE EXISTS (SELECT * FROM `student` WHERE `join_date` > '2017-03-21 00:00:00')
UNION ALL
SELECT * FROM `teacher`
WHERE NOT EXISTS (SELECT * FROM `student` WHERE `join_date` > '2017-03-21 00:00:00')
Note that the table schemas should be the same.

Insert query based on number of rows

I want a query to insert a row into a table I know it is simple but the scenario is the table should not have more than 5 rows. If table has more than five rows I need to remove the old row(Or replace with new row ) (Based on the insert time stamp) then i need to insert a new row.If number of rows less than count 5 then i can directly insert a row.
Please share me the query.
How about something like this.
declare #count int
SELECT #count=COUNT(*)
from EP_ANSWERS
IF (#count<5)
// DO your insert here
ELSE
DELETE FROM TABLE
WHERE inserttimestamp = (SELECT x.inserttimestamp
FROM (SELECT MAX(t.inserttimestamp) AS inserttimestamp
FROM TABLE t) x)
// DO your insert here
If it is impossible for the table to have more than 5 rows:
DELETE FROM yourtable
WHERE 5 <= (SELECT COUNT(*) FROM yourtable)
AND yourtimestamp = (SELECT MIN(yourtimestamp) FROM yourtable)
;
INSERT INTO yourtable ...
;
If it is possible for the table to have more than 5 rows:
DELETE FROM yourtable
WHERE 5 <= (SELECT COUNT(*) FROM yourtable)
AND yourtimestamp NOT IN (SELECT yourtimestamp
FROM yourtable
ORDER BY yourtimestamp DESC
LIMIT 4)
;
INSERT INTO yourtable ...
;
It sounds like you want to put a trigger on the table to maintain this rule, in MySQL the something like this should work
CREATE TRIGGER trg__my_table__limit_rows
BEFORE INSERT
ON my_table
FOR EACH ROW
BEGIN
IF ((SELECT COUNT(1) FROM my_table) = 5)
BEGIN
DELETE FROM my_table
WHERE id = (SELECT MIN(id) FROM my_table) -- change this to fit your logic for which record should be removed
END
END
Some of the code here is in pseudo (you didn't wrote your schema), but i wrote where you need to complete your own code.
DECLARE #NumberOfRowsToInsert INT = -- select from the data you want to insert
DECLARE #MaxNumberOfRows INT = 5
DECLARE #NumberOfExistingRows INT
DECLARE #Query VARCHAR(MAX) = 'SELECT TOP #rows id FROM SomeTable ORDER BY createdDate ASC'
SELECT #NumberOfExistingRows = COUNT(*)
FROM SomeTable
SET #Query = REPLACE(#Query,'#rows',
CAST(#NumberOfRowsToInsert - (#MaxNumberOfRows - #NumberOfExistingRows))) AS VARCHAR(1))
CREATE TABLE #IdsToDelete(id INT PRIMARY KEY)
INSERT INTO #IdsToDelete
EXEC(#Query)
DELETE FROM SomeTable
WHERE id IN (SELECT * FROM #IdsToDelete)
-- insert here..

MySQL Count values in a column, Update and replace value which has a limit amount

I have a problem with a MySQL Update statement.
I have more than 100.000 Entries in the table. So my approaches were not successful. (see below)
First, I want to count the number of values (thats easy):
SELECT values1 ,count(values1) FROM table
GROUP BY value1
HAVING COUNT(value1) <= 1000;
Second, i want to replace some values of the column values1 which appears only <= 1000 times.
So I tried these statement:
Update table as t
SET t.value1 = "limitAmount"
WHERE EXISTS (select value1 from
(select * from table) as f Group by f.value1
Having count(f.value1) <= 1000);
When i tried this SQL statement, i received:
Error Code 1205. Lock Wait timeout exceeded. Try restarting transaction.
Try this
Update
table as t
SET
t.value1 = "limitAmount"
WHERE
EXISTS (select value1 from (select * from table) as f where f.value1 = t.value1 Group by f.value1 Having count(f.value1) <= 1000);
Notice where f.value1 = t.value1 condition in the subquery
This statement works:
UPDATE test SET val="BLUB"
WHERE val IN
(SELECT val FROM (SELECT val FROM test GROUP BY val HAVING COUNT(val) <2000) war);
alternative:
Adding Values to a separate table
INSERT INTO helpTable (Value1) (select val FROM test
Group by val
Having count(val) <= 2000);
Select
Update test as t
SET t.val = "BLUB"
WHERE NOT EXISTS (Select Value1 FROM helpTable as h WHERE t.val = h.Value1);