Question

I have a little problem. I have developed an order management system. As a new feature, the user should now be able to see some statuses for each order in a listview.

My tables are like this:

orders:

id INT AUTO PRIMARY,
orderNo VARCHAR(20),
customerId INT,
salesmanId INT,
orderdate DATE

orderStatus:

id INT AUTO PRIMARY,
type ENUM (1,2,3,4),
orderId INT,
plannedDate DATE,
finalDate DATE,
isApproved ENUM(0,1)

And my current query for listing the data is:

SELECT
o.orderNo,
cst.name as customerName,
u.name as salesmanName,
o.orderdate,
t1.plannedDate as t1Planned,
t2.plannedDate as t2Planned,
t3.plannedDate as t3Planned,
t4.plannedDate as t4Planned,
t1.finalDate as t1Final,
t2.finalDate as t2Final,
t3.finalDate as t3Final,
t4.finalDate as t4Final,
t1.isApproved as t1App,
t2.isApproved as t2App,
t3.isApproved as t3App,
t4.isApproved as t4App
FROM orders as o
LEFT JOIN customers as cst ON ( cst.id = o.customerId)
LEFT JOIN users as u ON ( u.id = o.salesmanId )
LEFT JOIN orderStatus as t1 ON ( t1.type = 1 AND t1.orderId = o.id )
LEFT JOIN orderStatus as t2 ON ( t2.type = 2 AND t2.orderId = o.id )
LEFT JOIN orderStatus as t3 ON ( t3.type = 3 AND t3.orderId = o.id )
LEFT JOIN orderStatus as t4 ON ( t4.type = 4 AND t4.orderId = o.id )
ORDER BY
o.orderNo DESC

As you can see - a lot of Left joins, which I hope can be done in a different way. The main issue, is that this query is pretty slow. I hope someone can help me out. Thanks in advance.

Was it helpful?

Solution

UPDATE: You can use conditional aggregation

SELECT o.orderNo,
       c.name as customerName,
       u.name as salesmanName,
       o.orderdate,
       MAX(CASE WHEN s.type = 1 THEN plannedDate END) Planned1,
       MAX(CASE WHEN s.type = 2 THEN plannedDate END) Planned2,
       MAX(CASE WHEN s.type = 3 THEN plannedDate END) Planned3,
       MAX(CASE WHEN s.type = 4 THEN plannedDate END) Planned4,
       MAX(CASE WHEN s.type = 1 THEN finalDate   END) Final1,
       MAX(CASE WHEN s.type = 2 THEN finalDate   END) Final2,
       MAX(CASE WHEN s.type = 3 THEN finalDate   END) Final3,
       MAX(CASE WHEN s.type = 4 THEN finalDate   END) Final4,
       MAX(CASE WHEN s.type = 1 THEN isApproved  END) App1,
       MAX(CASE WHEN s.type = 2 THEN isApproved  END) App2,
       MAX(CASE WHEN s.type = 3 THEN isApproved  END) App3,
       MAX(CASE WHEN s.type = 4 THEN isApproved  END) App4
  FROM salesorderStatus s JOIN salesorders o
    ON s.orderId = o.id JOIN customers c
    ON o.customerId = c.id JOIN users u 
    ON o.salesmanId = u.id
 GROUP BY o.orderNo, c.name, u.name, o.orderdate
 ORDER BY o.orderNo DESC

Sample output:

+---------+--------------+--------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------+------+------+------+
| orderNo | customerName | salesmanName | orderdate  | Planned1   | Planned2   | Planned3   | Planned4   | Final1     | Final2     | Final3     | Final4     | App1 | App2 | App3 | App4 |
+---------+--------------+--------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------+------+------+------+
| E1015   | MICROSOFT    | Steffen      | 2013-10-01 | 2013-10-01 | 2013-10-01 | 2013-10-01 | 2013-10-01 | 2013-10-15 | 2013-10-15 | 2013-10-15 | 2013-10-15 | 1    | 0    | 1    | 0    |
| E1014   | ONLY         | Anders       | 2013-10-01 | 2013-10-01 | 2013-10-01 | 2013-10-01 | 2013-10-01 | 2013-10-15 | 2013-10-15 | 2013-10-15 | 2013-10-15 | 1    | 0    | 1    | 0    |
| E1013   | EXPERT       | Thomas       | 2013-10-01 | 2013-10-01 | 2013-10-01 | 2013-10-01 | 2013-10-01 | 2013-10-15 | 2013-10-15 | 2013-10-15 | 2013-10-15 | 1    | 0    | 1    | 0    |
...
+---------+--------------+--------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------+------+------+------+

Here is SQLFiddle demo

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top