Return group_concat with multiple rows - mysql

I have a orderLine table, where orders are attached to products. So my orderLine table can look like this:
orderID as coupled to orderLineId as a foreign key.
orderID productID
1 2
2 1
2 2
And my order table is like this:
orderLineId userID
1 1
1 1
2 1
But if I do the GROUP_CONCAT query:
SELECT orderLine.orderId,
GROUP_CONCAT(orderLine.productId)
FROM orders
INNER JOIN orderLine ON orders.orderLineId = orderLine.orderId
WHERE orders.orderId = 1
I get the result:
orderId, GROUP_CONCAT(orderLine.productId)
1 1,2,2
But I want to have:
orderId, GROUP_CONCAT(orderLine.productId)
1 1,2
2 2

You need to GROUP BY orderLine.orderId to get one row for each orderId:
SELECT orderLine.orderId,
GROUP_CONCAT(orderLine.productId)
FROM orders
INNER JOIN orderLine ON orders.orderLineId = orderLine.orderId
WHERE orders.orderId = 1
GROUP BY orderLine.orderId

Related

Count total orders and total products for each customer

I have 3 tables:
customers (CustomerID)
orders (OrderID, CustomerID)
orders_products (OrderID, ProductID)
I need to select each customer with their total orders and total number of products ordered by them.
To count total orders by each customer, the query is:
SELECT c.CustomerID, COUNT(o.OrderID) AS TotalOrders
FROM customers AS c
INNER JOIN orders AS o ON c.CustomerID = o.CustomerID
GROUP BY o.CustomerID
ORDER BY TotalOrders DESC
But how to count total number of products ordered by each customer?
I want something like below:
CustomerID
TotalOrders
TotalProducts
1
5
12
2
3
8
Question UPDATED with Sample Data:
I have updated my question with sample data of my three tables. The output of query suggested by some STO users here is also given below.
customers:
RowID
CustomerID
1
1
2
2
orders:
RowID
OrderID
CustomerID
1
101
1
2
102
1
3
103
2
4
104
1
orders_products:
RowID
OrderID
ProductID
1
101
1
2
101
2
3
102
1
4
103
1
5
104
1
Query:
SELECT c.CustomerID, COUNT(o.OrderID) AS TotalOrders, COUNT(op.ProductID) AS TotalProducts
FROM customers AS c INNER JOIN orders AS o
ON c.CustomerID = o.CustomerID
INNER JOIN orders_products AS op
ON o.OrderID = op.OrderID
GROUP BY c.CustomerID
ORDER BY TotalOrders DESC, TotalProducts DESC
Output (Incorrect):
CustomerID
TotalOrders
TotalProducts
1
4
4
2
1
1
You can see that customer with ID 1 has placed 3 orders and 5 products purchased under these orders. But query gives 4 total orders and also 4 total products for him. That's wrong!
Expected Output (Correct):
CustomerID
TotalOrders
TotalProducts
1
3
4
2
1
1
First ProductID is a primary key should be unique.
Second i try with different types of JOIN :
INNER JOIN: Returns records that have matching values in both tables
LEFT JOIN: Returns all records from the left table, and the matched records from the right table
RIGHT JOIN: Returns all records from the right table, and the matched records from the left table
CROSS JOIN: Returns all records from both tables
But nothing there is a mistake on the relation between the table.
In my case I changed orders table and it contains ProductID and CustomerID and it gives the correct result,
hope to help you
-- create
CREATE TABLE customer (
customerId INTEGER PRIMARY KEY
);
CREATE TABLE orders (
ordersId INTEGER PRIMARY KEY,
customerId INTEGER,
productsId INTEGER,
CONSTRAINT FK_CustomerOrder FOREIGN KEY (customerId)
REFERENCES customer(customerId),
CONSTRAINT FK_PersonProducts FOREIGN KEY (productsId)
REFERENCES products(productsId)
);
CREATE TABLE products (
productsId INTEGER PRIMARY KEY
);
-- insert
INSERT INTO customer VALUES (1);
INSERT INTO customer VALUES (2);
INSERT INTO orders VALUES (101, 1, 10001);
INSERT INTO orders VALUES (102, 1, 10001);
INSERT INTO orders VALUES (103, 2, 10005);
INSERT INTO orders VALUES (104, 1, 10003);
INSERT INTO products VALUES (10001);
INSERT INTO products VALUES (10002);
INSERT INTO products VALUES (10003);
INSERT INTO products VALUES (10004);
INSERT INTO products VALUES (10005);
-- fetch
SELECT c.customerId,
COUNT(o.ordersId) AS TotalOrders,
COUNT(op.productsId) AS TotalProducts
FROM customer AS c
INNER JOIN orders AS o ON c.customerId = o.customerId
INNER JOIN products AS op ON o.productsId = op.productsId
GROUP BY c.customerId

How can I retrieve Similar Orders In Mysql?

i need a query that should first look the oldest order which has status 0 (zero). and retrieves all the similar orders of that kind(matches exact total qty, itemSku and number of distinct items ordered).
***OrdersTable***
ID OrderNumber CustomerId Status created_at
1 123456 1 0 2018-01-01
2 234567 1 0 2018-01-02
3 345678 1 0 2018-01-03
4 456789 1 0 2018-01-04
***PurchasedProductsTable***
OrderId itemSku Qty
1 1000001 1
1 1000002 2
2 1000001 3
3 1000001 1
3 1000002 2
4 1000001 3
In the above table the query should first look at the oldest (created_at ASC) order (i.e with Id 1) having status 0 (in order table). and along with that order it should retrieves all the other orders that matches the same itemSku, qty and total distinct items count (in purchasedProducts table).
here order 1 and 3 matches the same itemSKu (1000001 and 1000002) and qty ( 1 and 2) and both have (2) distinct items count respectively so order 1 and 3 should be retrived at first.and when i marked order 1 and 3 as shipped (i.e chang status to 2).
and if i run query again it should retrive similar oders. now order 2 and 4 as order 2 and 4 are similar orders. (have same itemSkus (1000001, Qty (3) and distinct items count (1)).
please help thanks
You have to go trough your tables two times :)
Something like this :
SELECT DISTINCT O2.ID
FROM OrdersTable O1
INNER JOIN PurchasedProductsTable P1 ON O1.ID = P1.OrderId
INNER JOIN PurchasedProductsTable P2 ON P1.itemSku = P2.itemSku
AND P1.Qty = P2.Qty
INNER JOIN OrdersTable O2 ON O2.ID = P2.OrderId
WHERE O1.ID =
(SELECT ID FROM OrdersTable WHERE Status = 0
ORDER BY created_at ASC LIMIT 1)
AND (SELECT COUNT(*) FROM PurchasedProductsTable WHERE OrderId = O1.ID)
= (SELECT COUNT(*) FROM PurchasedProductsTable WHERE OrderId = O2.ID)
ORDER BY O2.ID ASC;
https://www.db-fiddle.com/f/65t9GgSfqMpzNVgnrJp2TR/2
You can get the earliest order via a limit and ordered by the date.
Then you can left join to get that order and any other order that at least has the same items.
Then once you have those order id's from the sub-query result, you can get the order details.
SELECT o.*
FROM
(
SELECT DISTINCT ord2.ID as OrderId
FROM
(
SELECT ID, CustomerId, Status
FROM OrdersTable
WHERE Status = 0
ORDER BY created_at
LIMIT 1
) AS ord1
JOIN PurchasedProductsTable AS pprod1
ON pprod1.OrderId = ord1.ID
LEFT JOIN OrdersTable ord2
ON ord2.CustomerId = ord1.CustomerId
AND ord2.Status = ord1.Status
LEFT JOIN PurchasedProductsTable pprod2
ON pprod2.OrderId = ord2.ID
AND pprod2.itemSku = pprod1.itemSku
AND pprod2.Qty = pprod1.Qty
GROUP BY ord1.CustomerId, ord1.ID, ord2.ID
HAVING COUNT(pprod1.itemSku) = COUNT(pprod2.itemSku)
) q
JOIN OrdersTable AS o ON o.ID = q.OrderId;
Test on RexTester here

Get id value from same table in query

I have this table setup:
orders:
id, order_nr
orders_cart:
id, orders_id,ref_backorder
Some data:
Orders:
id order_nr
1 012345
2 0123456
Orders_cart
id, orders_id, ref_backorder
1 2 1
1 1
the ref_backorder is a reference to another row in the same table.
Expected output:
id, ref_backorder
1 012345
2 null
My query:
SELECT o.id, o.ref_backorder`
FROM orders_cart o
??
LEFT JOIN orders ON o.ref_backorder` = orders.id
??
How can i get the ref_backorder as order_nr?
ref_backorder is an id from a row. In this case row 1, in row 1 we have an orders_id 2. The value of orders_id 2 (0123456) is the value what I want to show in the query.
Can you join the table to itself?
Seems the query could be this
select o.order_nr
from order
inner join orders_cart as c on c.ref_backorder = o.id
where c.orders_id = 2
SELECT A.id, A.orders_id, A.ref_backorder, B.order_nr FROM orders_cart AS A
JOIN orders AS B ON
A.orders_id = B.id

MySQL - remove non-duplicate rows from query

I'm running a query that selects details of orders, and I want to see only the orders that have gone through multiple stages. My data looks like:
id | order_id | action
1 100 1
2 100 2
3 100 4
4 101 1
5 102 2
6 103 1
7 103 2
So that only the rows for order_id 100 and 103 will be selected. This needs to be nested in a larger query.
You can use a subquery to get the orders that had multiple stages:
SELECT order_id
FROM your_table
GROUP BY order_id
HAVING COUNT(*)>1
then you can join this result back to your table:
SELECT o.*
FROM yourtable AS o INNER JOIN (
SELECT order_id
FROM your_table
GROUP BY order_id
HAVING COUNT(*)>1
) dup ON o.order_id = dup.order_id
Use group by with count and having
select *,count(order_id) as total from table
group by order_id
having total > 1
you can try this query:
select * from your_table
where ( select count(*) from your_table internal_table
where your_table .order_id = internal_table.order_id
) > 1

SQL Counting sums of rows

I have 2 tables.
Table 1: Fruits
id (int, autoincreasing, primary key)
some other junk
Table 2: Customers
has a 'fruit' column, this column contains an id from the fruit table.
i want to query all the customers, and come up with a list of all the fruit ID's and the number of times they are in use.
So this set up:
Fruits has
id name
1 orange
2 banana
3 apple
Customers has 6 rows like:
id fruit
1 1
2 1
3 2
4 2
5 2
6 3
Trying to write a query that Will give me:
fruit id purchase count
1 2
2 4
3 1
Try this
SELECT f.id as fruit_id, COUNT(1) AS purchase_count
FROM FRUITS f LEFT JOIN CUSTOMERS c
ON F.ID = c.fruit
GROUP BY f.id
Should just be a simple aggregate...
SELECT fruit_id, COUNT(fruit_id) AS purchase_count
FROM customers
GROUP BY fruit_id
ORDER BY fruit_id ASC;
untested
SELECT id, SUM(fruit) as "fruit id", "purchase count"
FROM Customers
GROUP BY id;