I'm writing a query to find an exact duplicate of the order by its pruducts IDs.
The conditions to find a duplicate are:
1) Order has the same product count.
2) All product IDs are the same.
Tried something like this, but it didn't work:
SELECT
order.*,
count(same_products.id),
count(all_products.id)
FROM orders
LEFT JOIN products AS all_products ON all_products.order_id = orders.id
LEFT JOIN products AS same_products
ON same_products.order_id = orders.id AND same_products.id IN (30868, 30862)
GROUP BY orders.id
HAVING count(same_products.id) = 4 AND count(all_products.id = 4)
if you want count duplicated rows you should avoid the all columns (*) selector because if you have incremental values in your columns this don't let you find the duplicated .
SELECT
order.id
count(same_products.id),
count(all_products.id)
FROM orders
LEFT JOIN products AS all_products ON all_products.order_id = orders.id
LEFT JOIN products AS same_products
ON same_products.order_id = orders.id AND same_products.id IN (30868, 30862)
GROUP BY orders.id
HAVING count(same_products.id) >1 OR count(all_products.id )> 1
and for duplicated row you should check for count> 1 (for both the count)
and be careful with count(all_products.id =4) if you need to filter for this value you should add this to the on condition for the related table eg:
SELECT
order.id
count(same_products.id),
count(all_products.id)
FROM orders
LEFT JOIN products AS all_products ON all_products.order_id = orders.id and all_products.id =4
LEFT JOIN products AS same_products
ON same_products.order_id = orders.id AND same_products.id IN (30868, 30862)
GROUP BY orders.id
HAVING count(same_products.id) >1
I am not clear what you really mean by duplicate, I assume from your description that it's 2 orders with the same products. This seems a little simplistic for example given
MariaDB [sandbox]> select * from orders;
+------+---------------------+-------------+
| id | order_created | customer_id |
+------+---------------------+-------------+
| 1 | 2016-01-01 00:00:00 | 1 |
| 2 | 2016-02-01 00:00:00 | 1 |
| 3 | 2016-03-01 00:00:00 | 1 |
| 4 | 2016-01-01 00:00:00 | 2 |
| 5 | 2016-02-01 00:00:00 | 2 |
| 6 | 2016-01-01 00:00:00 | 3 |
| 10 | 2016-12-01 00:00:00 | 4 |
+------+---------------------+-------------+
7 rows in set (0.00 sec)
MariaDB [sandbox]> select * from order_details;
+----+---------+-----------+------+
| id | orderid | productid | qty |
+----+---------+-----------+------+
| 1 | 1 | 1213 | 10 |
| 2 | 1 | 9999 | 10 |
| 3 | 2 | 8888 | 10 |
| 4 | 3 | 1213 | 10 |
| 5 | 4 | 2222 | 10 |
| 6 | 5 | 9999 | 30 |
| 7 | 5 | 1213 | 30 |
| 8 | 6 | 9999 | 30 |
| 9 | 6 | 1213 | 30 |
+----+---------+-----------+------+
9 rows in set (0.00 sec)
select orders1.*,orders2.*,t.*
from
(select * from
(
select orderid o1orderid,group_concat(productid order by productid) o1grp,sum(qty) qty1
from order_details
group by orderid
) o1
join
(select orderid o2orderid,group_concat(productid order by productid) o2grp, sum(qty) qty2
from order_details
group by orderid
) o2
on o2grp = o1grp and qty2 = qty1 and o2orderid > o1orderid
) t
join orders orders1 on t.o1orderid = orders1.id
join orders orders2 on t.o2orderid = orders2.id
returns
+------+---------------------+-------------+------+---------------------+-------------+-----------+-----------+-------+-----------+-----------+-------+
| id | order_created | customer_id | id | order_created | customer_id | o1orderid | o1grp | qty1 | o2orderid | o2grp | qty2 |
+------+---------------------+-------------+------+---------------------+-------------+-----------+-----------+-------+-----------+-----------+-------+
| 5 | 2016-02-01 00:00:00 | 2 | 6 | 2016-01-01 00:00:00 | 3 | 5 | 1213,9999 | 30,30 | 6 | 1213,9999 | 30,30 |
+------+---------------------+-------------+------+---------------------+-------------+-----------+-----------+-------+-----------+-----------+-------+
1 row in set (0.03 sec)
But customer number is different.
Related
I have the following tables:
Customer
| c_id | name |
| -------- | -------------- |
| 1 | Adam |
| 2 | Bradley |
| 3 | Chandler |
| 4 | Damian |
| 5 | Eric |
| 6 | Frank |
orders
| order_id | c_id | amount
| -------- | -------------- | -------------- |
| 1 | 1 | 50
| 2 | 1 | 2
| 3 | 2 | 15
| 4 | 2 | 22
| 5 | 2 | 10
| 6 | 2 | 7
| 7 | 3 | 7
| 8 | 3 | 2
| 9 | 5 | 18
| 10 | 5 | 24
| 11 | 6 | 60
| 12 | 6 | 1
I want to create a list of users who have order amounts over 50.
This list should include c_id, name and the sum of all their orders including those under 50.
so it should look like this:
| c_id | name | amount
| -------- | -------------- | -------------- |
| 1 |Adam | 52
| 6 | Frank | 61
You can use group by and having:
select c.c_id, c.name, sum(o.amount)
from orders o join
customers c
on o.c_id = c.c_id
group by c.c_id, c.name
having max(o.amount) > 50;
SELECT
c_id
, name
, SUM(amount) AS total_amount
FROM
orders a
INNER JOIN customer b
ON b.c_id = a.user_id
WHERE
c_id IN (
SELECT
user_id
FROM
orders
WHERE
amount >= 50)
GROUP BY c_id, name
Best to break this down into chunks:
Customers who have a total amount over 50:
SELECT user_id FROM orders GROUP BY user_id HAVING sum(amount) >= 50;
Sum of the amounts for each order for customers that meet the criteria above:
SELECT user_id, sum(amount) as order_total
FROM orders
WHERE user_id IN (SELECT user_id FROM orders HAVING sum(amount) >= 50 GROUP BY user_id)
GROUP BY user_id;
You can just join over to your customer table to grab the name. Didn't include since that is the more straightforward ask here.
I have the following table:
product
+-------------+------------+
| id_product | quantity |
+-------------+------------+
| 15 | 0 |
| 16 | 1 |
| 17 | 3 |
| 18 | 1 |
+-------------+------------+
And the other table is a subquery
+------------+-----------+
| id_product | total |
+------------+-----------+
| 15 | 1 |
| 17 | 1 |
| 18 | 4 |
+------------+-----------+
And I want to do is in a single update query, update the table products with the records returned by the subquery, making a sum, I can get one or many records from the subquery.
+-------------+------------+
| id_product | quantity |
+-------------+------------+
| 15 | 1 |
| 16 | 1 |
| 17 | 4 |
| 18 | 5 |
+-------------+------------+
I tried to make this update query, but it does not do what I want.
UPDATE product p
INNER JOIN (
SELECT id_product, count(*) as total
FROM othertable
GROUP BY id_product
) c ON p.id_product = c.id_product
SET p.quantity = c.total;
______EDIT______
UPDATE product p
INNER JOIN (
SELECT id_product, count(*) as total
FROM othertable
GROUP BY id_product
) c ON p.id_product = c.id_product
SET p.quantity = p.quantity + c.total
I have the following table:
+------------+--------+-----+
| reg_dat | status | id |
+------------+--------+-----+
| 2016-01-31 | 10 | 1 |
| 2017-06-31 | 12 | 1 |
| 2015-01-31 | 12 | 4 |
| 2017-01-25 | 5 | 4 |
| 2017-01-11 | 3 | 2 |
+------------+--------+-----+
I would like to do a mysql query to group the rows by id and keeping only the more recent date... so the output should be the following:
+------------+--------+-----+
| reg_dat | status | id |
+------------+--------+-----+
| 2017-06-31 | 12 | 1 |
| 2017-01-25 | 5 | 4 |
| 2017-01-11 | 3 | 2 |
+------------+--------+-----+
Unfortunately my code doesn't work...
select *
from table
group by id
order by id, reg_dat DESC
Have you some suggestions?
You can do that using a JOIN and a subquery
SELECT t.reg_dat, t.status, t.id
FROM table t
JOIN (SELECT max(reg_dat) max_date, id FROM table GROUP BY id) t1
ON t.reg_dat = t1.max_date AND t.id = t1.id
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
Is there any way to return distinct values with blank/null data from a table join. Best to explain with my example below.
Table "orders"
order_id | order_total
1 | 10
2 | 20
3 | 50
Table "order_items"
item_id | order_id | name | qty_ordered | base_price | row_total
1 | 1 | Product | 1 | 10 | 10
2 | 2 | Product | 1 | 10 | 10
3 | 2 | Product2 | 1 | 10 | 10
4 | 3 | Product | 2 | 10 | 20
5 | 3 | Product2 | 3 | 10 | 30
I'm trying to produce a result set that looks like this.
order_id | item_id | name | qty_ordered | base_price | row_total | order_total
1 | 1 | Product | 1 | 10 | 10 | 10
2 | 2 | Product | 1 | 10 | 10 | 20
null | 3 | Product2 | 1 | 10 | 10 | null
3 | 4 | Product | 2 | 10 | 20 | 50
null | 5 | Product2 | 3 | 10 | 30 | null
I only want the order_id and order_total once per order. I figure this is possible with some sort of join/distinct/sub query but alas nothing I've tried has worked so far.
Use:
SELECT x.order_id,
x.item_id,
x.name,
x.qty_ordered,
x.base_price,
x.row_total,
x.order_total
FROM (SELECT CASE
WHEN #order = o.order_id THEN NULL
ELSE o.order_id
END AS order_id,
oi.item_id,
oi.name,
oi.qty_ordered,
oi.base_price,
oi.row_total,
o.order_total,
CASE
WHEN #order = o.order_id THEN NULL
ELSE o.order_total
END AS order_total,
#order := o.order_id
FROM ORDER_ITEMS oi
JOIN ORDERS o ON o.order_id = oi.order_id
JOIN (SELECT #order := -1) r
ORDER BY o.order_id, oi.item_id) x
SELECT * FROM order_items
LEFT JOIN orders
ON (
order_items.order_id=orders.order_id
AND
order_items.item_id=(
SELECT MIN(item_id)
FROM order_items a
WHERE a.order_id=order_items.order_id
)
)
This should work because the nested query always returns the same MIN(item_id) for each order, and it only joins for that item.
But this is a very, very ugly piece of sql. Don't do this.