LIMIT offset or OFFSET in an UPDATE SQL query - mysql

I have a table similar to this:
| 0 | X |
| 1 | X |
| 2 | X |
| 3 | Y |
| 4 | Y |
| 5 | X |
| 6 | X |
| 7 | Y |
| 8 | Y |
| 9 | X |
I'd like to replace first 2 occurrences of X with X1, and then 4 next occurrences with X2 so that the resulting table looks like this:
| 0 | X1 |
| 1 | X1 |
| 2 | X2 |
| 3 | Y |
| 4 | Y |
| 5 | X2 |
| 6 | X2 |
| 7 | Y |
| 8 | Y |
| 9 | X2 |
The table in question is of course much bigger and the number of occurrences would thus be higher too so manual editing is not a solution.
I'd like to do something like this:
UPDATE table SET column = 'X' WHERE column = 'X2' LIMIT 90, 88
but unfortunately MySQL doesn't seem to support OFFSET in UPDATE queries... Is there any way to do this?

I don't know whether you have id filed available in table or not, but you can use WHERE id BETWEEN 88 AND 90, MySQL does not support Offset in update query, but you can do this by limiting using BETWEEN command

Try this:
UPDATE table SET column = 'X1' WHERE id IN(SELECT id FROM (SELECT id FROM table WHERE column = 'X' LIMIT 2) as u);
and then
UPDATE table SET column = 'X2' WHERE id IN(SELECT id FROM (SELECT id FROM table WHERE column = 'X' LIMIT 4) as u);

Related

How to append rows or retrigger query (in a loop?) based on result value of a row?

Summary: I have a query that currently gives me N rows, depending on the value given in WHERE clause. These rows may contain a certain value in a specific column (container_id from a different table). If the value is > 0, I want to repeat the query with the value as the new WHERE clause and append the result to the table. This should be repeated until the value is = 0 (or NULL).
What I've already tried:
I tried to expand the WHERE clause with an OR / AND statement
WHERE
c.id = 55 OR
c.id = i.container_id;
but this gives me more or no results than expected.
SELECT DISTINCT
c.*,
container_items.slot,
items.id AS itemid,
items.item_template_id,
items.container_id,
items.quantity
FROM
items i,
containers c
LEFT JOIN
container_items ON container_items.containerid = c.id
LEFT JOIN
items ON items.id = container_items.itemid
WHERE
c.id = 55;
The upper query gives me the following result:
id | Name | x | x | container_id | quantity
--------------------------------------------------------
55 | Bin | x | x | 63 | 1
55 | Bin | x | x | 0 | 6
I now want to append the rows, that would be given, if I ran query again with c.id = 63:
id | Name | x | x | container_id | quantity
--------------------------------------------------------
63 | Basket | x | x | 67 | 1
63 | Basket | x | x | 0 | 6
Since the next result also contains container_id > 0, I want to repeat and append the rows, etc. until no further rows can be appended, because of an invalid or 0 value:
id | Name | x | x | container_id | quantity
--------------------------------------------------------
67 | Basket | x | x | 0 | 1
67 | Basket | x | x | NULL | 6
So the expected result would the combined from above:
id | Name | x | x | container_id | quantity
--------------------------------------------------------
55 | Bin | x | x | 63 | 1
55 | Bin | x | x | 0 | 6
63 | Basket | x | x | 67 | 1
63 | Basket | x | x | 0 | 6
67 | Basket | x | x | 0 | 1
67 | Basket | x | x | NULL | 6
I think I'm missing a major keyword in MySQL to do this. All links would be helpful :)

MySQL select all pinned and some other flagged record to reach limit

I have a "products" table where are stored all the store products, some of them are flagged with "hp" flag and some also with "hppin" flag
I need 2 flags because i pick 10 random products from all of the "hp" flagged ( they could 100 or more ) but I need to get all the pinned one.
The pinned need to be always inside the 10 selected products
I need 10 records = all "hppin" flag + random "hp" flag
example table
PRODUCTS
| id | name | hppin | hp |
| 1 | prod1 | y | y |
| 2 | prod2 | n | y |
| 3 | prod3 | y | y |
| 4 | prod4 | n | y |
| 5 | prod5 | n | n |
| 6 | prod6 | y | y |
| 7 | prod7 | n | y |
| 8 | prod8 | n | y |
| 9 | prod9 | n | y |
| 10 | prod10 | n | y |
| 11 | prod11 | n | y |
| 12 | prod12 | n | y |
| 13 | prod13 | n | y |
| 14 | prod14 | n | n |
| 15 | prod15 | n | y |
I could solve this with 2 query but I would like to know if is possible
to do it just in one query.
The result should be record 1,3,6 + 7 random record with hp = y
You can phrase your query using a union between the two sets of data which you want to obtain. The first half of the below union retrives hppin yes records. The second half obtains hp yes records. We then apply a limit of 10 records using an ordering which gives preference to the hppin matches first. The hp records would only enter the result set if there were fewer than 10 hppin records, which would be the case for your sample data.
SELECT id, name, hppin, hp, 1 AS position
FROM PRODUCTS
WHERE hppin = 'y'
UNION ALL
SELECT id, name, hppin, hp, 2
FROM PRODUCTS
WHERE hp = 'y'
ORDER BY
position, RAND()
LIMIT 10

Alternate order by logic in MySQL

I'm looking to allow for a custom ordering logic through mySQL that allows the following data set:
+----+-----------------+------------+-------+--+
| ID | item | Popularity | Views | |
+----+-----------------+------------+-------+--+
| 1 | A special place | 3 | 10 | |
| 2 | Another title | 5 | 12 | |
| 3 | Words go here | 1 | 15 | |
| 4 | A wonder | 2 | 8 | |
+----+-----------------+------------+-------+--+
To return an order that alternates, row by row, by popularity and then by views, so the return results look like:
+----+-----------------+------------+-------+--+
| ID | item | Popularity | Views | |
+----+-----------------+------------+-------+--+
| 3 | Words go here | 1 | 15 | |
| 2 | Another title | 5 | 12 | |
| 4 | A wonder | 2 | 8 | |
| 1 | A special place | 3 | 10 | |
+----+-----------------+------------+-------+--+
Where you will see the first row returns the 'most popular', the second row returns the most views, the third row returns the second most popular, and the 4th row returns the 2nd most views.
Currently I'm gathering an entire table through mySQL twice, and then merging these results in PHP. This isn't going to cut it when the database is large. Is this possible in mysql at all?
I guess something along these lines could work. Consider the following:
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,x INT NOT NULL
,y INT NOT NULL
);
INSERT INTO my_table VALUES
(1,3,10),
(2,5,12),
(3,1,15),
(4,2, 8)
(5,4, 1);
We can rank x and y in turn, and then arrange those ranks in a single list - so will have x1,y1,x2,y2,etc - but all rows will appear twice; once for the x rank and once for the y rank...
SELECT * FROM
(
( SELECT a.*, COUNT(*) rank FROM my_table a JOIN my_table b ON b.x <= a.x GROUP BY a.id )
UNION ALL
( SELECT a.*, COUNT(*) rank FROM my_table a JOIN my_table b ON b.y <= a.y GROUP BY a.id )
) n
ORDER BY rank
+----+---+----+------+
| id | x | y | rank |
+----+---+----+------+
| 5 | 4 | 1 | 1 |
| 3 | 1 | 15 | 1 |
| 4 | 2 | 8 | 2 |
| 4 | 2 | 8 | 2 |
| 1 | 3 | 10 | 3 |
| 1 | 3 | 10 | 3 |
| 5 | 4 | 1 | 4 |
| 2 | 5 | 12 | 4 |
| 2 | 5 | 12 | 5 |
| 3 | 1 | 15 | 5 |
+----+---+----+------+
Now we can just grab the lowest rank for each id...
SELECT id
, x
, y
FROM
(
( SELECT a.*, COUNT(*) rank FROM my_table a JOIN my_table b ON b.x <= a.x GROUP BY a.id )
UNION ALL
( SELECT a.*, COUNT(*) rank FROM my_table a JOIN my_table b ON b.y <= a.y GROUP BY a.id )
) m
GROUP
BY id,x,y
ORDER
BY MIN(rank);
+----+---+----+
| id | x | y |
+----+---+----+
| 3 | 1 | 15 |
| 5 | 4 | 1 |
| 4 | 2 | 8 |
| 1 | 3 | 10 |
| 2 | 5 | 12 |
+----+---+----+
Incidentally, this should be faster with variables - but I cannot make that solution work at present - senior moment, perhaps.

Distinct on specific column in Hive

I am running Hive 071 I have a table, with mulitple rows, with the same column value e.g.
| x | y |
| 1 | 2 |
| 1 | 3 |
| 1 | 4 |
| 2 | 2 |
| 3 | 2 |
| 3 | 1 |
I want to have the x column unique, and remove rows that have the same x val e.g.
| x | y |
| 1 | 2 |
| 2 | 2 |
| 3 | 2 |
or
| x | y |
| 1 | 4 |
| 2 | 2 |
| 3 | 1 |
are both good as distinct works only on the whole rs in hive, I couldn't find a way to do it
help please Tx
Some options:
1) This will give you the max value of y for each value of x
select x, max(y) from table1 group by x
Equally you could use avg() or min()
2) OR, you could collect all the values of y in a list:
select x, collect_set(y) from table1 group by x
This will give you:
x|y
1|2,3,4
2|2
3|1,2

Distinct on specific column in Hive

I am running Hive 071
I have a table, with mulitple rows, with the same column value
e.g.
x | y |
---------
1 | 2 |
1 | 3 |
1 | 4 |
2 | 2 |
3 | 2 |
3 | 1 |
I want to have the x column unique, and remove rows that have the same x val
e.g.
x | y |
---------
1 | 2 |
2 | 2 |
3 | 2 |
or
x | y |
---------
1 | 4 |
2 | 2 |
3 | 1 |
are both good
as distinct works only on the whole rs in hive, I couldn't find a way to do it
help please
Tx
You can use the distinct keyword:
SELECT DISTINCT x FROM table
try following query to get result :
select A.x , A.y from (select x , y , rank() over ( partition by x order by y) as ranked from testingg)A where ranked=1;