mysql increment against another column - mysql

Here is my Products table.
+---------+------------+-----------+
| item_id | item_order | item_name |
+---------+------------+-----------+
| 10 | | Item x |
| 12 | | Item b |
| 33 | | Item j |
| 39 | | Item k |
+---------+------------+-----------+
I want to run a sql query in phpMyAdmin so that item_order will increment as item_id number decreases. I want to arrange products on my Featured Products page by item_order. At a later time I'll rearrange numbers in 'item_order' column to give certain products more prominence, but for now here is how table will look after query update...
+---------+------------+-----------+
| item_id | item_order | item_name |
+---------+------------+-----------+
| 10 | 4 | Item x |
| 12 | 3 | Item b |
| 33 | 2 | Item j |
| 39 | 1 | Item k |
+---------+------------+-----------+

How about this?
SELECT *, (
SELECT COUNT(1) FROM Products pd WHERE pd.item_id >= p.item_id
) item_order
FROM Products p

Related

mysql group by, max, count implementaion

tables
items table
------------------
| id | item |
------------------
| 1 | pearl |
| 2 | ruby |
| 3 | gold |
| 4 | diamond |
------------------
transaction table
--------------------------------------------------
| item_id | sell_price | created_at |
--------------------------------------------------
| 1 | 10 | 2020-08-21 01:50:24 |
| 1 | 20 | 2020-08-22 05:51:10 |
| 3 | 20 | 2020-08-23 06:52:05 |
| 3 | 30 | 2020-08-24 22:55:07 |
| 4 | 50 | 2020-08-25 20:58:18 |
| 2 | 10 | 2020-08-26 12:59:55 |
--------------------------------------------------
expected output:
--------------------------------------------------------------------
| item_id | name | quantity | price | created_at |
--------------------------------------------------------------------
| 1 | pearl | 2 | 20 | 2020-08-22 05:51:10 |
| 2 | ruby | 1 | 10 | 2020-08-26 12:59:55 |
| 3 | gold | 2 | 30 | 2020-08-24 22:55:07 |
| 4 | diamond | 1 | 50 | 2020-08-25 20:58:18 |
--------------------------------------------------------------------
the query
SELECT
items.id AS item_id,
items.item,
COUNT(transaction.item_id) AS quantity,
MAX(transaction.price) AS sell_price
FROM transaction
LEFT JOIN items
ON transaction.item_id = items.id
GROUP BY transaction.item_id;
My query above works perfectly fine without transaction.created_at on select clause, but when I put select transaction.created_at it throws an error:
SELECT list is not in GROUP BY clause and contains nonaggregated column 'db.transaction.created_at' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
From the desired output you shared, it looks like you're trying to query the maximum created_at:
SELECT
items.id AS item_id,
items.item,
COUNT(transaction.item_id) AS quantity,
MAX(transaction.price) AS sell_price,
MAX(created_at) AS created_at -- Here!
FROM transaction
LEFT JOIN items
ON transaction.item_id = items.id
GROUP BY transaction.item_id;
When using GROUP BY, just list all columns that are in SELECT and that not inside an aggregate function.
SELECT
items.id AS item_id,
items.item,
COUNT(transaction.item_id) AS quantity,
MAX(transaction.sell_price) AS sell_price,
MAX(transaction.created_at) AS created_at
FROM transaction
LEFT JOIN items
ON transaction.item_id = items.id
GROUP BY items.id, items.item;
See db-fiddle.

Get those items which are ordered after they have been delivered

I have two tables, namely itemOrders and itemDelivered.
itemOrders
+-------+---------+--------+
| id | orderid | itemid |
+-------+---------+--------+
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 2 | 1 |
| 4 | 2 | 2 |
| 5 | 3 | 1 |
| 6 | 3 | 2 |
+-------+---------+--------+
And
itemDelivered
+-------+-------------+--------+
| id | orderId | itemid |
+-------+-------------+--------+
| 1 | 2 | 2 |
| 2 | 3 | 2 |
| 3 | 2 | 1 |
+-------+-------------+--------+
From the above scenario I want all those distinct items whose max orderId in the table itemDelivered is less than max orderId in the table itemOrders.
In the above example I should get itemid 1 as the result, as it's max orderid is 2 in table itemDelivered, which is less than its max orderid in table itemOrders which is 3.
I wrote the following query but it gives me both the items, 1 and 2 as item No. 2 doesn't have orderId 1 in itemDelivered table.
SELECT DISTINCT( itemid )
FROM itemorders
WHERE orderid NOT IN (SELECT orderid
FROM itemdelivered)
You can LEFT JOIN between the two table using itemid, and GROUP BY on the itemid.
Eventually use HAVING clause to consider only those itemid values, where MAX(itemdelivered.orderid) < MAX(itemorders.orderid)
View on DB Fiddle
SELECT io.itemid
FROM itemorders AS io
LEFT JOIN itemdelivered AS id
ON id.itemid = io.itemid
GROUP BY io.itemid
HAVING MAX(id.orderid) < MAX(io.orderid)
OR MAX(id.orderid) IS NULL
Result
| itemid |
| ------ |
| 1 |
Ok, manage to write a query which gives the desired output.
SELECT io.itemid
FROM itemorders as io
LEFT JOIN itemdelivered AS id ON io.orderid = id.orderid AND io.itemid = id.itemid
WHERE id.itemid IS NULL
HAVING MAX(id.orderid) IS NULL
ORDER BY io.id

Getting rows which have a certain revision_status

I am using mysql and I have two tables:
Product Table:
| id | name | prices | revision_id |
|----|-----------|--------|-------------|
| 1 | Produkt 1 | 10 | 1 |
| 2 | Produkt 1 | 4 | 2 |
| 3 | Produkt 1 | 2 | 3 |
| 4 | Product 2 | 42 | 4 |
| 5 | Produkt 2 | 43 | 5 |
| 6 | Produkt 3 | 78 | 6 |
Each product has had price changes. That is why the name is still the same, but the products have a different price.
Revisions Table:
| id | revision_status |
|----|-----------------|
| 1 | 1 |
| 2 | 0 |
| 3 | 0 |
| 4 | 1 |
| 5 | 0 |
| 6 | 1 |
Inside the revision table, 0 indicates an open change, not approved change. 1 indicates - closed - an approved change.
Expected Result:
| id | name | prices | revision_id | revision_status |
|----|-----------|--------|-------------|-----------------|
| 1 | Produkt 1 | 10 | 1 | 1 |
| 2 | Produkt 1 | 4 | 2 | 0 |
| 3 | Produkt 1 | 2 | 3 | 0 |
| 4 | Product 2 | 42 | 4 | 1 |
| 5 | Produkt 2 | 43 | 5 | 0 |
Basically I want all products that have revisions - a revision_status of 0 on it, to see which products actually have revisions.
For example.: Product 3 does not have any price changes, so it should not appear in the final result.
I tried the following:
select *
from product
JOIN revisions
on product.revisions_id = revisions.id
ORDER
BY product.name
However, I still get Product 3 in my table and I am not sure how to get all products that have a revision_status of 0 on it.
I highly appreciate your replies!
In my interpretation you are looking for the products which have more than one revision. Filtering only on revision_status = 0 would not produce your expected result. The following query may answer your question (looking for those products which have more than 1 revision):
SELECT *
FROM product AS p
INNER JOIN revisions AS r ON p.revision_id = r.id
WHERE p.name IN (
SELECT p.name
FROM product AS p
INNER JOIN revisions AS r ON p.revision_id = r.id
GROUP BY p.name
HAVING COUNT(r.revision_status) > 1)
ORDER BY p.name
This would produce your expected result. See example at sqlfiddle.

How to get info from three tables with a MIN (MySQL)

I have four tables, like these:
items
| id | name | category |
-------------------------
| 1 | item1 | toy |
| 2 | item2 | toy |
| 3 | item3 | home |
-------------------------
items2
| id | name | category | size |
--------------------------------
| 1 | itemA | toy | s |
| 2 | itemB | home | l |
--------------------------------
prices
| items.id | price |
--------------------
| 1 | 10 |
| 1 | 15 |
| 2 | 20 |
| 3 | 25 |
| 3 | 20 |
--------------------
prices
| items2.id | price |
--------------------
| 1 | 15 |
| 2 | 50 |
| 2 | 40 |
--------------------
I need to get a result which have both, items and items2, with the MIN of each price. In this example the result should be something like this:
| id | name | category | size | minprice |
-------------------------------------------
| 1 | item1 | toy | null | 10 |
| 2 | item2 | toy | null | 20 |
| 3 | item3 | home | null | 20 |
| 1 | itemA | toy | s | 15 |
| 2 | itemB | home | l | 40 |
-------------------------------------------
I also should be able to ORDER BY minprice, but I'm sure when I know how to join them I can do that too.
Thanks in advance!
I would suggest that you merge the tables items and items2. If a field doesn't apply to an item (such as size in this case), that is what null is for.
I haven't tested that this works but you want something like:
SELECT i.id, name, category, null as size, min(prices.price) from items i
JOIN prices on prices.id = i.id
GROUP BY i.id, i.name, i.category, size
UNION ALL
SELECT i2.id, name, category, size, min(prices2.price) from items2 i2
JOIN prices2 on prices2.id = i2.id
GROUP BY i2.id, i2.name, i2.category, i2.size
From what I can tell, you are over complicating things. You only need one table. For tuples in the item relation where there is no size, simply mark it as null.
This is probably an oversimplification. If prices are "sales" or something similar, you could use a left join to build the relation you are looking for
so
SELECT i.id, i.name, i.category, i.size, p.price as min_price FROM items i LEFT JOIN price p where p.price <= 40 ORDER BY min_price

MySQL : exclude rows where id appears in two separate columns of table

I have a table that looks like this:
| id | order_id | product_id | category_id |name | cost | returned_product_id |
| 3100 | 900 | 0125 | 3 | Foo | 14 | NULL |
| 3101 | 901 | 0145 | 3 | Bar | 10 | NULL |
| 3102 | 901 | 2122 | 3 | Baz | 11 | NULL |
| 3103 | 900 | 0125 | 3 | Foo | -14 | 3100 |
| 3104 | 902 | 0125 | 3 | Foo | 14 | NULL |
| 3105 | 902 | 0125 | 3 | Foo | -14 | 3104 |
| 3106 | 903 | 0125 | 3 | Foo | 14 | NULL |
The id is a single line item of an order where product_id was included. If the product is returned, a new line item is created with a new id. There is one of each product, and it is possible to repurchase a returned item again, and return it again.
I'm joining the table data with data from other tables given certain conditions. As a final condition, I am attempting to exclude any line items that were originally returned. This is in attempt to perform a single query that essentially gives me all product_ids ever purchased and that have not been returned, like this:
select product_id
from orders o,
line_items i
where o.state = 'paid'
and o.id = i.order_id
and i.category_id = 3
and i.product_id not in (select li.returned_product_id
from line_items li
where li.refunded_product_id is not null
and li.product_id = 3)
Even though I have indexes on both the id and returned_product_id, the query above is really slow (thousands of lines), where if my subselect queried for the id, it's fast.
If your query is from the table that you exposed the content, the line:
and i.id not in (select li.returned_product_id
will look in the id of the table and not the id of the product, wright?
That should be
and i.product_id not in (select li.returned_product_id
something like:
select distinct i.product_id from
line_items i left join line_items j
on i.product_id = j.refunded_product_id
where j.refunded_product_id is null
?