Hy, i want reduce my table and updating himself (group and sum some columns, and delete rows)
Source table "table_test" :
+----+-----+-------+----------------+
| id | qty | user | isNeedGrouping |
+----+-----+-------+----------------+
| 1 | 2 | userA | 1 | <- row to group + user A
| 2 | 3 | userB | 0 |
| 3 | 5 | userA | 0 |
| 4 | 30 | userA | 1 | <- row to group + user A
| 5 | 8 | userA | 1 | <- row to group + user A
| 6 | 6 | userA | 0 |
+----+-----+-------+----------------+
Wanted table : (Obtained by)
DROP TABLE table_test_grouped;
SET #increment = 2;
CREATE TABLE table_test_grouped
SELECT id, SUM(qty) AS qty, user, isNeedGrouping
FROM table_test
GROUP BY user, IF(isNeedGrouping = 1, isNeedGrouping, #increment := #increment + 1);
SELECT * FROM table_test_grouped;
+----+------+-------+----------------+
| id | qty | user | isNeedGrouping |
+----+------+-------+----------------+
| 1 | 40 | userA | 1 | <- rows grouped + user A
| 3 | 5 | userA | 0 |
| 6 | 6 | userA | 0 |
| 2 | 3 | userB | 0 |
+----+------+-------+----------------+
Problem : i can use another (temporary) table, but i want update initial table, for :
grouping by user and sum qty
replace/merge rows into only one by group
The result must be a reduce of initial table, group by user, and qty summed.
And it's a minimal exemple, and i don't want full replace inital from table_test_grouped, beacause in my case, i have another colum (isNeedGrouping) for decide if y group or not.
For flagged rows "isNeedGrouping", i need grouping.
For this exemple, a way to do is sequentialy to :
CREATE TABLE table_test_grouped SELECT id, SUM(qty) AS qty, user, isNeedGrouping FROM table_test WHERE isNeedGrouping = 1 GROUP BY user ;
DELETE FROM table_test WHERE isNeedGrouping = 1 ;
INSERT INTO table_test SELECT * FROM table_test_grouped ;
Any suggestion for a simpler way?
It is probably simpler to empty and refill the table than to try and update/delete. Also, the aggregation logic can be simplified to avoid the use for a user variable.
You could write this as:
create table table_test_tmp as
select min(id) id, sum(qty) qty, user, isneedgrouping
from table_test tt
group by tt.user, case when tt.isneedgrouping = 0 then tt.id end;
truncate table table_test; -- back it up first!
insert into table_test (id, qty, user, isneedgrouping)
select id, qty, user, isneedgrouping
from table_test_tmp;
drop table table_test_tmp;
I am looking for a solution to find an unused number in the table. The most of the solutions I came across so far is creating a temporary table with all the numbers and used left join to find the unused number. In my case, I have no opportunity to create a temporary table.
The number range with leading zeros: 0001-1999. These numbers are dialing pad numbers and it has to be 4 digits in length.
listings table:
+----+--------+------------+
| id | title | pad_number |
+----+--------+------------+
| 1 | Foo | 0001 |
| 2 | bar | 0005 |
| 3 | Baz | 1999 |
| 10 | FooBar | 0002 |
+----+--------+------------+
Expected result:
0003
Is there any way to retrieve the number?
I would do this as:
select lpad(min(pad_number) + 1, 4, '0')
from t
where not exists (select 1 from t t2 where t2.pad_number = t.pad_number + 1);
Use not exists.
select lpad(cast(cast(pad_number as unsigned)+1 as char(4)),4,'0')
from tbl t
where not exists (select 1 from tbl t1
where cast(t.pad_number as unsigned)=cast(t1.pad_number as unsigned)-1)
and cast(pad_number as unsigned) >=0 and cast(pad_number as unsigned) < 1999
order by 1
limit 1
I know this should be super easy, but I just can't get my head around it.
I have a table with values like this:
+----+-------+
| ID | VALUE |
+----+-------+
| 1 | 100 |
| 2 | 200 |
| 3 | 100 |
| 4 | 300 |
+----+-------+
I want to check if the most recent row (id 4) have the value 100.
I can't use LIMIT 1 or anything, and I'm sure I should use MAX() somehow, but I don't know where to start.
Thanks
Try this:
SELECT * -- (or others fields you need)
FROM YOUR_TABLE AS A
WHERE A.ID = (SELECT MAX(B.ID)
FROM YOUR_TABLE AS B) AND A.VALUE = 100 --(OR ELSE)
Table Mytable1
Id | Actual
1 ! 10020
2 | 12203
3 | 12312
4 | 12453
5 | 13211
6 | 12838
7 | 10l29
Using the following syntax:
SELECT AVG(Actual), CEIL((#rank:=#rank+1)/3) AS rank FROM mytable1 Group BY rank;
Produces the following type of result:
| AVG(Actual) | rank |
+-------------+------+
| 12835.5455 | 1 |
| 12523.1818 | 2 |
| 12343.3636 | 3 |
I would like to take AVG(Actual) column and UPDATE a second existing table Mytable2
Id | Predict |
1 | 11133
2 | 12312
3 | 13221
I would like to get the following where the Actual value matches the ID as RANK
Id | Predict | Actual
1 | 11133 | 12835.5455
2 | 12312 | 12523.1818
3 | 13221 | 12343.3636
IMPORTANT REQUIREMENT
I need to set an offset much like the following syntax:
SELECT #rank := #rank + 1 AS Id , Mytable2.Actual FROM Mytable LIMIT 3 OFFSET 4);
PLEASE NOTE THE AVERAGE NUMBER ARE MADE UP IN EXAMPLES
you can join your existing query in the UPDATE statement
UPDATE Table2 T2
JOIN (
SELECT AVG(Actual) as AverageValue,
CEIL((#rank:=#rank+1)/3) AS rank
FROM Table1, (select #rank:=0) t
Group BY rank )T1
on T2.id = T1.rank
SET Actual = T1.AverageValue
Trying to sort rows from lowest to highest continually, or rather repeatedly using MySql. For example: if a column has the following values: 1,3,2,4,2,1,4,3,5, then it should end up like this 1,2,3,4,5,1,2,3,4. So it goes from lowest to highest, but tries to sort again from lowest to highest multiple times.
For large sets, the semi-JOIN operation (the approach in the answer from Strawberry) may create an unwieldy resultset. (Then again, MySQL may have some optimizations in there.)
Another alternative available in MySQL is to use "user variables", like this:
SELECT r.mycol
FROM ( SELECT IF(q.mycol=#prev,#seq := #seq + 1,#seq := 1) AS seq
, #prev := q.mycol AS mycol
FROM mytable q
JOIN (SELECT #prev := NULL, #seq := NULL) p
ORDER BY q.mycol
) r
ORDER BY r.seq, r.mycol
Let me unpack that a bit, and explain what it's doing, starting with the inner query (inline view aliased as r.) We're telling MySQL to get the column (mycol) containing the values you want to sort, e.g. 1,3,2,4,2,1,4,3,5 and we're telling MySQL to order these in ascending sequence: 1,1,2,2,3,3,4,4,5.
The "trick" now is to use a MySQL user variable, so that we can compare the mycol value from the current row to the mycol value from the previous row, and we use that to assign an ascending sequence value, from 1..n on each distinct value.
With that resultset, we can tell MySQL to order by that assigned sequence value first, and then by the value from mycol.
If there is a unique id on each row, then a correlated subquery can be used to get an equivalent result (although this approach is very unlikely to perform as well on large sets)
SELECT r.mycol
FROM mytable r
ORDER
BY ( SELECT COUNT(1)
FROM mytable q
WHERE q.mycol = r.mycol
AND q.id <= r.id
)
, r.mycol
Here's the setup for the test case:
CREATE TABLE mytable (id INT, mycol INT);
INSERT INTO mytable (id, mycol) VALUES
(1,1),(2,3),(3,2),(4,4),(5,2),(6,1),(7,4),(8,3),(9,5);
there is no order two time just this
ORDER BY column ASC
Let's pretend that the PK is a unique integer. Consider the following...
CREATE TABLE seq(id INT NOT NULL PRIMARY KEY,val INT);
INSERT INTO seq VALUES (8,1),(4,2),(1,3),(2,4),(7,0),(6,1),(3,2),(5,5);
SELECT * FROM seq ORDER BY val;
+----+------+
| id | val |
+----+------+
| 7 | 0 |
| 6 | 1 |
| 8 | 1 |
| 3 | 2 |
| 4 | 2 |
| 1 | 3 |
| 2 | 4 |
| 5 | 5 |
+----+------+
SELECT x.*
, COUNT(*) rank
FROM seq x
JOIN seq y
ON y.val = x.val
AND y.id <= x.id
GROUP
BY id
ORDER
BY rank
, val;
+----+------+------+
| id | val | rank |
+----+------+------+
| 7 | 0 | 1 |
| 6 | 1 | 1 |
| 3 | 2 | 1 |
| 1 | 3 | 1 |
| 2 | 4 | 1 |
| 5 | 5 | 1 |
| 8 | 1 | 2 |
| 4 | 2 | 2 |
+----+------+------+