Get those items which are ordered after they have been delivered - mysql

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

Related

How to select max value from rows and join to another table

I am trying to join two tables with respect to the max values for the values column. I would like to produce the expected results as shown below based on the max value while joining
select * from order
-------------------------
| ID | value | Name |
-------------------------
| 1 | 23 | REM |
| 2 | 0 | SER |
| 3 | 13 | MH |
| 4 | 3 | MH |
| 5 | 1 | MP |
-------------------------
select * from product
-------------------------
| ID | value | Name |
-------------------------
| 1 | 2 | ABC |
| 2 | 2 | DEG |
| 3 | 17 | XYZ |
-------------------------
Desired result:
-------------------------
| ID | Value | Name |
-------------------------
| 1 | 23 | REM |
| 2 | 2 | DEG |
| 3 | 17 | XYZ |
| 4 | 3 | MH |
| 5 | 1 | MP |
-------------------------
I have tried something like below but it's not fetching the value (NAME) from other table
SELECT
MAX(IF(a.value >b.value , a.value ,b.value )) AS Value
from order a left join product b on a.ID= b.ID
Please suggest how to get the expected result from these two tables.
Below is for BigQuery Standard SQL
#standardsql
select as value array_agg(struct(id, value, name) order by value desc limit 1)[offset(0)]
from
(
select * from `project.dataset.order`
union all
select * from `project.dataset.product`
)
group by id
with output
You can do this using a full join:
select id,
(case when p.val is null or p.val < o.val then o.val else p.val end),
(case when p.val is null or p.val < o.val then o.name else p.name end)
from product p full join
order o
using (id);
I just find this the simplest way to think about the problem.

Select count where two columns aren't equal to 0

I have a table as below mentioned:
|----------------|-------------|-------------|
| a_id | m_id | e_id |
|----------------|-------------|-------------|
| 1 | 1 | 0 |
| 2 | 2 | 2 |
| 3 | 3 | 3 |
| 4 | 1 | 1 |
| 5 | 4 | 4 |
|----------------|-------------|-------------|
I need a query that performs the task that a_id should have either m_id or e_id not equal to 0.
So, I wrote the query as follows which returns count 5:
SELECT count(a_id) from ids where (e_id!=0 or m_id!=0)
I need a_id should have distinct m_id != 0. That should return count 4.
use count(distinct
select count(distinct m_id) from ids where e_id!=0 or m_id!=0

Mysql delete similar rows according to specific columns except the ones with highest id

my table has duplicate row values in specific columns. i would like to remove those rows and keep the row with the latest id.
the columns i want to check and compare are:
sub_id, spec_id, ex_time
so, for this table
+----+--------+---------+---------+-------+
| id | sub_id | spec_id | ex_time | count |
+----+--------+---------+---------+-------+
| 1 | 100 | 444 | 09:29 | 2 |
| 2 | 101 | 555 | 10:01 | 10 |
| 3 | 100 | 444 | 09:29 | 23 |
| 4 | 200 | 321 | 05:15 | 5 |
| 5 | 100 | 444 | 09:29 | 8 |
| 6 | 101 | 555 | 10:01 | 1 |
+----+--------+---------+---------+-------+
i would like to get this result
+----+--------+---------+---------+-------+
| id | sub_id | spec_id | ex_time | count |
+----+--------+---------+---------+-------+
| 5 | 100 | 444 | 09:29 | 8 |
| 6 | 101 | 555 | 10:01 | 1 |
+----+--------+---------+---------+-------+
i was able to build this query to select all duplicate rows from multiple columns, according to this question
select t.*
from mytable t join
(select id, sub_id, spec_id, ex_time, count(*) as NumDuplicates
from mytable
group by sub_id, spec_id, ex_time
having NumDuplicates > 1
) tsum
on t.sub_id = tsum.sub_id and t.spec_id = tsum.spec_id and t.ex_time = tsum.ex_time
but now im not sure how to wrap this select with a delete query to delete the rows except for the ones with highest id.
as shown here
You can modify your sub-select query, to get maximum value of id for each duplication combination.
Now, while joining to the main table, simply put a condition that id value will not be equal to the maximum id value.
You can now Delete from this result-set.
Try the following:
DELETE t
FROM mytable AS t
JOIN
(SELECT MAX(id) as max_id,
sub_id,
spec_id,
ex_time,
COUNT(*) as NumDuplicates
FROM mytable
GROUP BY sub_id, spec_id, ex_time
HAVING NumDuplicates > 1
) AS tsum
ON t.sub_id = tsum.sub_id AND
t.spec_id = tsum.spec_id AND
t.ex_time = tsum.ex_time AND
t.id <> tsum.max_id

sql Select Orders with multiple addresses

I'm trying to select orders, which are send at least two times with the same addressId to a customer.
This is my table structure:
Customer Table:
+------------+-----------+
| customerId | addressId |
+------------+-----------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
+------------+-----------+
Relation for Addresses to Orders
+---------+-----------+
| orderId | addressId |
+---------+-----------+
| 1 | 1 |
| 2 | 2 |
| 3 | 2 |
| 4 | 3 |
| 5 | 4 |
| 6 | 4 |
+---------+-----------+
Order Table
+----+------------+-------+
| id | orderEntry | total |
+----+------------+-------+
| 1 | timestamp | 4711 |
| 2 | timestamp | 0815 |
| 3 | timestamp | 1337 |
+----+------------+-------+
Now I want a output like this:
+------------+---------+-----------+
| customerId | orderId | addressId |
+------------+---------+-----------+
| 2 | 2 | 2 |
| 2 | 3 | 2 |
| 4 | 5 | 4 |
| 4 | 6 | 4 |
+------------+---------+-----------+
I've tried to get the right result with these Query, but I think I can't count the addresses this way.
SELECT C.`customerId`, AO.`orderId`, AO`addressId`
FROM customer AS C
JOIN address_order AS AO ON AO.addressId = C.addressId
JOIN order AS O ON O.id = AO.orderId
GROUP BY AO.`orderId`
HAVING (COUNT(AO.`addressId`) > 1);
With these Query I only get a result like this:
+------------+---------+-----------+
| customerId | orderId | addressId |
+------------+---------+-----------+
| 2 | 2 | 2 |
| 4 | 5 | 4 |
+------------+---------+-----------+
I don't see the usage of order table here. However you can use the order table into the consideration if you want to make sure that the order table data and address_order should have data. You can write the query as
select
c.customerId,
ao.orderId,
ao.addressId
from customer c
join address_order ao on ao.addressId = c.addressId
join (
select addressId, count(*) as tot from address_order
group by addressId having tot = 2
)x on x.addressId = ao.addressId
If you want to make sure all the orderId from customer_order are in the order table then you can add another join at the end as
join `order` o on o.id = ao.orderId
Try this
SELECT customerId FROM customer INNER JOIN (SELECT * FROM address_order GROUP BY addressId
HAVING (COUNT(addressId) > 1)) AS t1 ON customer.addressId=t1.addressId

Find the maximum value(s) from a column and selecting their rows

After looking at other examples I still have not been able to find a solution, that is why I am asking for some help.
My table structure:
V_id | name | group_id | other columns
----------------------
1 | | 1
2 | | 1
3 | | 2
4 | | 3
5 | | 3
I have been struggling to build a query, to select all the rows which have the maximum value from the group_id column.
therefore output should be like this:
V_id | name | group_id | other columns
----------------------
4 | | 3
5 | | 3
which I believe can be solved by selecting all records where group_id is the highest.
and also need a query to get all the other remaining rows.
which in this case, should be like this:
V_id | name | group_id | other columns
----------------------
1 | | 1
2 | | 1
3 | | 2
which I believe can be done by selecting all records where group_id < Max(group_id)
for the first part of the problem,
SELECT *
FROM tableName
WHERE group_id = (SELECT MAX(group_ID) FROM TableName)
and for the second part,
SELECT *
FROM tableName
WHERE group_id < (SELECT MAX(group_ID) FROM TableName)
You can use JOIN for that:
SELECT a.*
FROM Table1 a
JOIN (SELECT MAX(Group_ID) AS MAXID
FROM Table1) B
ON a.Group_id = B.MaxID;
Result:
| V_ID | NAME | GROUP_ID |
----------------------------
| 4 | (null) | 3 |
| 5 | (null) | 3 |
For the remaining rows use LEFT JOIN with a condition like this:
SELECT a.*
FROM Table1 a
LEFT JOIN (SELECT MAX(Group_ID) AS MAXID
FROM Table1) B
ON a.Group_id = B.MaxID
WHERE B.MaxID IS NULL;
Result:
| V_ID | NAME | GROUP_ID |
----------------------------
| 1 | (null) | 1 |
| 2 | (null) | 1 |
| 3 | (null) | 2 |
See this SQLFiddle