I got a set of results like this:
| id |
| 1 |
| 2 |
| 3 |
| 4 |
I'm trying to get
| id |
| 4 |
| 1 |
| 2 |
| 3 |
Is there any elegant way to achieve this using an SQL script?
You can use the mod operator, % to ORDER BY
DECLARE #maxId AS INT
SELECT #maxId = MAX(Id) FROM MyTable
SELECT id FROM MyTable
ORDER BY Id % #maxId
You can get further rotations by adding to Id, ie
ORDER BY (Id + 1) % #maxId
get you
3
4
1
2
Working SQL Fiddle (which I just found out exists)
http://sqlfiddle.com/#!3/a7f15/5
ok i'll take a stab at the SQL.
select case when id > 3 then 0
else 1
end
, id
from mytable
order by 1,2
Related
I have a table I am trying to use two aggregate values to create another column. For example
My table looks like this
| id | col_a | col_b
---------------------
| 1 | 5 | 10
| 1 | 15 | 20
| 2 | 1 | 2
| 2 | 3 | 4
| 2 | 5 | 6
And I want the output to be
| id | total_a | total_b | grand_total
---------------------------------------
| 1 | 20 | 30 | 50
| 2 | 9 | 12 | 21
And I tried
SELECT id,
SUM(col_a) AS total_a,
SUM(col_b) AS total_b,
(total_a + total_b) AS grand_total
FROM my_table
GROUP BY id
But that gives me an error Unknown column 'total_a' in 'field list'
I also tried using variables like this, but I don't think I am using variables correctly here.
SELECT id,
#a := SUM(col_a) AS total_a,
#b := SUM(col_b) AS total_b,
(SELECT #a + #b) AS grand_total
FROM my_table
GROUP BY id
What am I doing wrong here? It seems like this should be simple.
Nevermind. I figured it out. It is in fact really simple
SELECT id,
SUM(col_a) AS total_a,
SUM(col_b) AS total_b,
(SUM(col_a) + SUM(col_b)) AS grand_total
FROM my_table
GROUP BY id
mysql question... So I would like to auto populate a number, but I would like it to be based on another field. I'm not sure how to explain it other than using this example:
Field 1 | Field 2 (auto populate)
1 | 1
2 | 1
2 | 2
2 | 3
3 | 1
3 | 2
2 | 4
2 | 5
Is there a mysql function expression that can be added to the column?
I know I could do this in my Python script that is feeding the values, but I have to assume it will be faster if the function is baked into mysql.
UPDATE:
Let me add some clarification...
Field 1 will get filled with a value from a script.
There will be multiple entries of Field 1 that are the same number.
I would like Field 2 to auto populate to have a unique number WITHIN that Field 1 number.
You can just store the field1 and generate field2 as increasing integer value within each field1 using user variables like this:
select
t.field1,
#rn := if(field1 = #f1, #rn + 1, if(#fi := field1, 1, 1)) field2
from (
select
t.*
from your_table t
order by field1 --very important
) t cross join (select #rn := 0, #f1 := -1) t2
You could use a trigger which is a function which automatically runs on certain conditions.
Here is the manual http://dev.mysql.com/doc/refman/5.7/en/trigger-syntax.html.
You could for example use a AFTER UPDATE or AFTER INSERT trigger for this purpose.
Setting aside the usual caveats relating to MyISAM tables...
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(field1 INT NOT NULL
,field2 INT NOT NULL AUTO_INCREMENT
,PRIMARY KEY(field1,field2)
) ENGINE = MyISAM;
INSERT INTO my_table (field1) VALUES
(1),(2),(2),(2),(3),(3),(2),(2);
SELECT * FROM my_table;
+--------+--------+
| field1 | field2 |
+--------+--------+
| 1 | 1 |
| 2 | 1 |
| 2 | 2 |
| 2 | 3 |
| 2 | 4 |
| 2 | 5 |
| 3 | 1 |
| 3 | 2 |
+--------+--------+
..but I would question whether there's really any sense storing this information at all...
...hence, a more robust approach...
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(field1 INT NOT NULL
,field2 INT NOT NULL AUTO_INCREMENT PRIMARY KEY
) ENGINE = InnoDB;
INSERT INTO my_table (field1) VALUES
(1),(2),(2),(2),(3),(3),(2),(2);
SELECT x.field1
, CASE WHEN #prev = field1 THEN #i:=#i+1 ELSE #i:=1 END i
, #prev:=field1 prev
FROM my_table x
, (SELECT #prev:=null,#i:=0) vars
ORDER
BY field1
, field2;
+--------+------+------+
| field1 | i | prev |
+--------+------+------+
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 2 | 2 | 2 |
| 2 | 3 | 2 |
| 2 | 4 | 2 |
| 2 | 5 | 2 |
| 3 | 1 | 3 |
| 3 | 2 | 3 |
+--------+------+------+
You probably want to create a trigger. Something like the following:
CREATE TRIGGER `populate_field_2` BEFORE INSERT ON `table_name` FOR EACH ROW BEGIN
DECLARE _new_val INT DEFAULT 0;
SELECT MAX(field_2)+1 INTO _new_val FROM 'table_name' WHERE field_1 = NEW.field_1;
SET NEW.field_2 = _new_val;
END
This would populate field_2 each time you created a new row. You can update the logic to create whatever value for field2 you need.
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)
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 |
+----+------+------+
Let's say I have a mySQL table whose structure is like this:
mysql> select * from things_with_stuff;
+----+---------+----------+
| id | counter | quantity |
+----+---------+----------+
| 1 | 101 | 1 |
| 2 | 102 | 2 |
| 3 | 103 | 3 |
+----+---------+----------+
My goal is to "expand" the table so I end up with something like:
mysql> select * from stuff;
+----+---------+
| id | counter |
+----+---------+
| 1 | 101 |
| 2 | 102 |
| 3 | 102 |
| 4 | 103 |
| 5 | 103 |
| 6 | 103 |
+----+---------+
And I want to do this "expansion" using only mysql. Note that I end up with a row per quantity and per counter. Any suggestions? A stored procedure is not an option here (I know they offer while loops).
Thanks!
The following will do the trick as long as some_large_table has a length greater than or equal to the largest quantity in things_with_stuff. For example, let some_large_table be a big fact table in a data warehouse.
SELECT #kn:=#kn+1 AS id, counter
FROM (SELECT #kn:=0) k, things_with_stuff ts
INNER JOIN (
SELECT #rn:=#rn+1 AS num
FROM (SELECT #rn:=0) t, some_large_table
) nums ON num <= ts.quantity;
Assuming there is a maximum value for quantity, you could do:
INSERT INTO things SELECT counter FROM things_with_stuff WHERE quantity > 0;
INSERT INTO things SELECT counter FROM things_with_stuff WHERE quantity > 1;
INSERT INTO things SELECT counter FROM things_with_stuff WHERE quantity > 2;
--... and so on until the max.
It's a bit of a hack but it should do the job.
If the ordering is important you could do a clean up afterwards.
I have sometimes in databases a table named num (number) with a single column i, filled with all integers from 1 to 1000000. It's not hard to make such a table and populate it.
Then you could use this if stuff.id is auto incremented:
INSERT INTO stuff
( counter )
SELECT ts.counter
FROM things_with_stuff AS ts
JOIN num
ON num.i <= ts.quantity