'MYSQL or Laravel Eloquent How To Count The Detail From This Order

[MYSQL QUERY / LARAVEL ELOQUENT QUESTION]

Hi, I really need some help with MYSQL Query this 3 tables I have. The order table and the details it's a manually input on our system.

I'm new in MYSQL, need a help not a judge.

PERSON TABLE (persons)

ID PERSON_NAME
1 Jackie
2 Chan

ORDER TABLE (orders)

ID PERSON_ID ORDER_DATE
1 1 (Jackie) January 01, 2022
2 1 (Jackie) January 02, 2022
3 2 (Chan) January 02, 2022
4 2 (Chan) January 03, 2022
5 1 (Jackie) January 04, 2022
6 1 (Jackie) January 05, 2022

ORDER DETAIL TABLE (order_details)

ID ORDER_ID DESCRIPTION PRICE
1 1 Apple 100
2 1 Orange 80
3 1 Mango 90
4 3 Grape 50
5 3 Apple 100
6 4 Apple 100
7 5 Orange 80
8 5 Mango 90

QUESTION

Here I combined the 3 tables, and this is what I got, it's showing Order ID 2 and 6 doesn't have any order detail added (manually) on our system let's say I forgot to add the detail. So I need to show it as an error on person page.

SELECT
  o.id as order_id,
  p.name as person_name,
  o.date as order_date,
  COUNT(od.id) as count_order_detail,
  SUM(od.price) as subtotal
FROM persons p
JOIN orders o ON o.person_id = p.id
JOIN order_details od ON od.order_id = o.id
GROUP BY o.order_id
ORDER_ID PERSON_NAME ORDER_DATE COUNT_ORDER_DETAIL SUBTOTAL
1 Jackie January 01, 2022 3 270
2 Jackie January 02, 2022 0 0
3 Chan January 02, 2022 2 150
4 Chan January 03, 2022 1 100
5 Jackie January 04, 2022 2 170
6 Jackie January 05, 2022 0 0

EXPECTED QUERY RESULT ON MYSQL TABLE

Here is the result I expected showing the result of order with no detail.

PERSON_NAME ORDERS ERROR_ORDER
Jackie 4 Orders 2
Chan 2 Orders -

How can I do it ? I tried to COUNT the COUNT but it's messed up.

Note : Sorry for the bad grammar.



Solution 1:[1]

Well I could not get the hypen into the ERROR_ORDER when there are no errors, but this should be pretty close otherwise:

SELECT name AS PERSON_NAME, 
       CONCAT(count(id), ' Orders') AS ORDERS, 
       CONCAT(count(order_id), ': ', 
           GROUP_CONCAT(IF(ISNULL(order_id), id, NULL))) AS 'ERROR_ORDER'
FROM (
    SELECT name, o.id, order_id
      FROM persons p JOIN orders o ON o.person_id = p.id
        LEFT JOIN order_details od ON od.order_id = o.id
     GROUP BY name, o.id, order_id
) x
GROUP BY name
ORDER BY ORDERS DESC;

Which gives:

PERSON_NAME ORDERS ERROR_ORDER
jackie 4 Orders 2: 2,6
chan 2 Orders null

...or by screenshot:

enter image description here

Example dbfiddle with all the data.

=====

But, if you really only want to show 2 in the last column, without the order references, then change the last part of the select to be:

CONCAT(SUM(IF(ISNULL(order_id), 1, null))) AS 'ERROR_ORDER'

Which would look like this:

PERSON_NAME ORDERS ERROR_ORDER
jackie 4 Orders 2
chan 2 Orders null

...or by screenshot:

enter image description here

Example fiddle for this example.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1