How to simplfy this query? - mysql

Query 1:
SET #count = 0;
UPDATE a_daily_copy_copy
SET a_daily_copy_copy.Cummulative_Target = #count:= target + #count
where a_daily_copy_copy.Site_id = 1
and a_daily_copy_copy.Year=4
and a_daily_copy_copy.Billing_cycle=1
ORDER BY date
Query 2: Modified the a_daily_copy_copy.Billing_cycle=2
SET #count = 0;
UPDATE a_daily_copy_copy
SET a_daily_copy_copy.Cummulative_Target = #count:= target + #count
where a_daily_copy_copy.Site_id = 1
and a_daily_copy_copy.Year=4
and a_daily_copy_copy.Billing_cycle=2
ORDER BY date
I'm a beginner and as of now I'm running the query every time manually by editing the query 1 , and I know both queries can be consolidated into a single query.
I tried solving with Group by function but couldnt come up with Please help me.
Have screened the table:

Looks to me that you can just do:
SET #count = 0;
UPDATE a_daily_copy_copy
SET a_daily_copy_copy.Cummulative_Target = #count:= target + #count where a_daily_copy_copy.Site_id = 1 and a_daily_copy_copy.Year=4 and a_daily_copy_copy.Billing_cycle IN (1, 2)
ORDER BY date
...unless I've missed a difference between the two queries other than the billing cycle.

Related

How to split count() query into 10 groups in my sql

I am currently using mysql and I have to split the data into 10 groups.
For example, if the total count of data is 90, it should go like
1~9,
10~18,
19~27,
28~36,
37~45,
46~54,
55~63,
64~72,
73~81,
82~90.
if the total count of data is 100, it should go like
1~10,
11~20,
21~30,
31~40,
41~50,
51~60,
61~70,
71~80,
81~90,
91~100.
Can anyone give me a clue to split the data into 10 groups. I used rownum, but it did not work....
select total.row_num,
total.name,
total.reg,
total.id,
total.motspd
from(
select
(#row_num:=#row_num+1) AS row_num,
cg.group_name as name,
td.reg_date as reg,
td.car_id as id,
td.mcu_motspd as motspd
from
cartracker.tracker_data td
left join car c on (c.car_device_no = td.car_id)
left join car_group cg on (c.car_group_no = cg.car_group_no)
where cg.car_group_no = "1"
group by DATE_FORMAT(td.reg_date, "%Y%M%d%h%m")
)total
This is a result of a query, but it shows wrong row numbers.I want row_num goes from 0 to the end number of the data. but, in the picture, it starts from 44,713. can anyone help me to fix row num as it starts from 0 to the end number of the data.
attached image
I am going by the question in the title:
I am currently using mysql and I have to split the data into 10 groups.
That is exactly what the function ntile() does. So:
select t.*,
ntile(10) over (order by <whatever>) as tile
from t;
I have no idea what the query has to do with this question.
Haven't realize OP want with dynamic table BEFORE re-edit, this is not cleaver and require a lot of time to process though. switch a with OP table name and create rownumber first.
DECLARE #TotalNum INT;
DECLARE #Num INT;
DECLARE #NUm2 INT;
DECLARE #COUNTS INT;
SET #COUNTS = (select count(rownum) from a)/10
SET #TotalNum = 10
SET #Num =1
SET #Num2 =0
WHILE #Num <= #TotalNum
BEGIN
update a
set a.flag = #Num
where a.rownum >= (#COUNTS)*#NUM2+1 and a.rownum <= #NUM*(#COUNTS)
SET #Num = #NUM + 1
SET #Num2 = #NUM2 + 1
END

How to increment using a SQL variable within an update statement

I am trying to increment a column using an #count variable in SQL. I have tried multiple attempts that I will list below that all result in:
Error Code: 1064
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ...
First was:
SET #count = 65;
UPDATE table t
SET t.Revision = CHAR(#count)
, #count = #count + 1
WHERE t.hidden = 0;
I am trying to increment every row currently as a proof of concept that this works.
Second was:
DECLARE t CURSOR FOR
SELECT * FROM table
WHERE t.hidden = 0;
OPEN t;
FETCH NEXT FROM t;
WHILE ##FETCH_STATUS = 0
BEGIN
UPDATE table t2 SET t2.Revision = 'D' WHERE t2.id1 = t.id1 AND t2.id2 = t.id2;
END;
END
CLOSE t;
DEALLOCATE t;
Once again I am just trying to see if I can set a standard variable using a while loop before I implement incrementing as a proof of concept that it works.
I am not sure why either of these attempts is failing but any help would be appreciated.
Here is how your first example should work(inside of some loop):
first you set your count value, then you update
SET #count = 65;
UPDATE CUSTOMER t
SET t.LName = CONVERT(#count, char)
where t.FName = 'a';
...and then increase that count and you update again...
set #count = #count + 1;
UPDATE CUSTOMER t
SET t.LName = CONVERT(#count, char)
where t.FName = 'a';
But that should be in a procedure for example.
Here is the DEMO. I it a small example and I hope you will find it helpful.
Cheers!
You can try the following solution:
SET #count = 64; -- so the first increment is 65 (starting on A).
UPDATE table_name t
SET t.Revision = CHAR(#count:=#count+1)
WHERE t.hidden = 0;
or (shorter):
UPDATE table_name t, (SELECT #count:=64) t2
SET t.Revision = CHAR(#count:=#count+1)
WHERE t.Hidden = 0;
demo on dbfiddle.uk

MySQL Variable Assignment via Procedure Not Working Correctly

In the code below, I'm trying go through the results of endDateTable row by row, comparing the current row's endDate to the previous row's endDate. If there has been any change since the previous, we increment #revisionNum. However, upon populating the new table, all of the #revisionNum entries are 0. What am I doing wrong?
NOTE: I'm using prepared statements in this manner since doing a straightforward SELECT into a variable gives a syntax error due to the LIMIT clause not allowing a variable in our version of MySQL.
BEGIN
DECLARE _currentEndDate DATETIME DEFAULT now();
DECLARE _priorEndDate DATETIME DEFAULT now();
SET #ResultsCount = (SELECT COUNT(*) FROM mainTable);
SET #j = 0;
WHILE #j < #ResultsCount DO
SET #revisionNum = 0;
/*CURRENT END DATE*/
SET #appResultQueryCurrent = CONCAT('
SELECT
end_date
INTO _currentEndDate
FROM endDateTable
LIMIT ', #j, ', 1'
);
PREPARE currentQueryStmt FROM #appResultQueryCurrent;
EXECUTE currentQueryStmt;
/*PREVIOUS END DATE*/
SET #appResultQueryPrior = CONCAT('
SELECT
end_date
INTO _priorAppEndDate
FROM endDateTable
LIMIT ', IF(#j = 0, 0, #j - 1), ', 1'
);
PREPARE priorQueryStmt FROM #appResultQueryPrior;
EXECUTE priorQueryStmt;
SET #revisionNum = IF(
#j = 0 OR (_currentEndDate = _priorEndDate),
#revisionNum,
IF(
_currentEndDate != _priorEndDate,
#revisionNum + 1,
#revisionNum
)
);
INSERT INTO finalTable (RevisionNum)
SELECT
#revisionNum AS RevisionNum
FROM endDateTable;
SET #j = #j +1;
END WHILE;
END $$
You don't need a loop, you can use INSERT INTO ... SELECT ..., incrementing the variable in the select query.
You also need an ORDER BY criteria to specify how to order the rows when comparing one row to the previous row.
INSERT INTO finalTable (RevisionNum, otherColumn)
SELECT revision, otherColumn
FROM (
SELECT IF(end_date = #prev_end_date, #revision, #revision := #revision + 1) AS revision,
#prev_end_date := end_date,
otherColumn
FROM endDateTable
CROSS JOIN (SELECT #prev_end_date := NULL, #revision := -1) AS vars
ORDER BY id) AS x
DEMO
The offset value in the LIMIT clause is tenuous without an ORDER BY.
Without an ORDER BY clause, MySQL is free to return results in any sequence.
There is no guarantee that LIMIT 41,1 will return the row before LIMIT 42,1, or that it won't return the exact same row as LIMIT 13,1 did.
(A table in a relational database represents an unordered set of tuples, there is no guaranteed "order" or rows in a table.)
But just adding ORDER BY to the queries isn't enough to fix the Rube-Goldberg-esque rigmarole.
In the code shown, it looks like each time through the loop, we're inserting a copy of endDateTable into finalTable. If that's 1,000 rows in endDateTable, we're going to get 1,000,000 rows (1,000 x 1,000) inserted into finalTable. Not at all clear why we need so many copies.
Given the code shown, it's not clear what the objective is. Looks like we are conditionally incrementing revisionNum, the end result of which is the highest revision num. Just guessing here.
If there is some kind of requirement to do this in a LOOP construct, within a procedure, I'd think we'd do a cursor loop. And we can use procedure variables vs user-defined variables.
Something along these lines:
BEGIN
DECLARE ld_current_end_date DATETIME;
DECLARE ld_prior_end_date DATETIME;
DECLARE li_done INT;
DECLARE li_revision_num INT;
DECLARE lcsr_end_date CURSOR FOR SELECT t.end_date FROM `endDateTable` t ORDER BY NULL;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET li_done = TRUE;
SET li_done = FALSE;
SET li_revision_num = 0;
OPEN lcsr_end_date;
FETCH lcsr_end_date INTO ld_current_end_date;
SET ld_prior_end_date = ld_current_end_date;
WHILE NOT li_done DO
SET li_revision_num = li_revision_num + IF( ld_current_end_date <=> ld_prior_end_date ,0,1);
SET ld_prior_end_date := ld_current_end_date;
FETCH lcsr_end_date INTO ld_current_end_date;
END WHILE;
CLOSE lcsr_end_date;
INSERT INTO `finalTable` (revisionnum) VALUES (li_revision_num);
END $$
Note the "order by" clause on the SELECT, its not clear what the rows should be ordered on, so we're using a literal as a placeholder.
As the end result, we insert a single row into finalTable.
Again, it's not clear what the code in the question is supposed to achieve, but doing a cursor loop across ordered rows would be much more efficient than a bazillion dynamic SQL executions fetching individual rows.

MySQL copy multiple row-entries to another position

I want to copy a big amount of values from a specific row and specific date to the same row, but another date. I have tried it with the SQL UPDATE SET function and two different tables, but the SET will only use the first value and copy it to the right date-columns.
At this picture you see the results:
And this is one of the queries I tried:
UPDATE Test_tab t
SET t.testValue =
(SELECT testValue
FROM Test_tab
WHERE testDate > '2015-10-01' AND testDate < '2015-10-31'
LIMIT 1)
WHERE t.testDate > '2015-11-01' AND t.testDate < '2015-11-31'
you may try like this
CREATE PROCEDURE your_proc()
BEGIN
DECLARE cont INTEGER;
SET cont = 0;
SET max = SELECT count(*) FROM test_tab;
WHILE cont < max DO
UPDATE Test_tab t SET t.testValue =(SELECT testValue FROM Test_tab WHERE testDate >'2015-10-01' AND testDate <'2015-10-31'
LIMIT cont, 1) WHERE t.testDate > '2015-11-01' AND t.testDate < '2015-11-31'
SET cont = cont + 1;
END WHILE;
END;

Counting with MySQL

Is there a way to count an Int in a MySQL Update Query?
Currently i have
UPDATE mails SET uid = 4275
and i want something like
UPDATE mails SET uid = (4275++)
Do you want to do something like this?
SELECT #i:=425;
UPDATE mails SET uid = #i:=#i+1;
UPDATE mails SET uid = uid + x
x meaning any number
I didn't get your question properly but I am just answering as I understood
UPDATE mails SET uid = uid + 1
i.e to increment current uid by the lastuid + 1
If you need to update the table so that increment each uid with 1 then you can do this:
UPDATE mails
SET uid = uid + 1;
But if you need to increament each value uid by an incremental value try this:
SET #counter = 0;
UPDATE mails m1
INNER JOIN
(
SELECT *, (#counter := #counter +1) as counter
FROM mails
) m2 ON m1.uid = m2.uid
SET m1.uid = m1.uid + m2.counter
And if you want to count from 4275 on, just set the counter to SET #counter = 4275
UPDATE mails SET uid = uid +1 will add 1 to every uid column.
try
UPDATE mails SET uid = uid+1
where uid = 4275
You can keep your own counter
declare #curr_uid integer;
SET #curr_uid = 4275; -- initial uid
update mails
set uid = #curr_uid , #curr_uid = #curr_uid + 1