2016-01-17 20 views
7

Mam 4 tabele.Wartość zamówienia i zamówienia nie jest pobierana poprawnie w mysql

table_orders

order_id 
customer_id 
order_datetime 
order_payment_type 
order_delivery_date 
delivery_time_slot 

table_order_details

order_id 
product_id 
varient_id 
quantity 
product_mrp 
product_sell_price 
product_name 

table_order_status

order_id 
status_id 
status_datetime 

table_order_status_values ​​

value_id 
value_desc 

Chcę uzyskać identyfikator zamówienia, kwotę zamówienia, datę zamówienia, ilość zamówienia, czas zamówienia, wartość_desc.

Używam tego zapytania.

SELECT oo.order_id, oo.amount, oo.date, oo.quantity, oo.time, value_desc 
FROM 
(
    SELECT s.order_id, SUM(OD.product_sell_price * OD.quantity) as amount, 
     DATE_FORMAT(o.order_datetime, '%d/%m/%Y') as date, SUM(OD.quantity) 
     as quantity, TIME(o.order_datetime) as time, MAX(status_id) as laststatus 
    FROM table_orders o 
    INNER JOIN table_order_details AS OD ON o.order_id = OD.order_id 
    INNER JOIN table_order_status s ON s.order_id = o.order_id 
    GROUP BY o.order_id 
)oo 

INNER JOIN table_order_status_values ON value_id = laststatus 

order by order_id DESC 

próbki danych:

Table_orders

1 1 2015:12:12:19:42:47 1 2015:12:14 1 

table_order_details

1 12 3 1 21.00 20.00 abcd 
1 13 2 2 100.00 90.00 efgh 

table_order_status

1 1 2015:12:12:19:42:47 
1 2 2015:12:12:20:42:47 

table_order_status_values ​​

1 NEW ORDER 
2 CONFIRM 
3 Delivered 

Z powyższego wynik zapytania jest:

1 400.00 12:12:2015 6 19:42:47 CONFIRM 

Ale spodziewane wyjście jest:

1 200.00 12:12:2015 3 19:42:47 CONFIRM 

jestem coraz kwotę zamówienia i porządku wartości ilościowych dwukrotnie (lub trzy) na podstawie numeru statusu dla danego zamówienia.

Jak rozwiązać ten problem? Jakakolwiek pomoc będzie doceniona.

+0

można pokazać przykładowe wyjście? Prawdopodobnie jest to spowodowane przez sprzężenie na 'table_order_status'. Być może potrzebujesz tylko uzyskać najnowszy status, a nie wszystkie wartości pośredniczące: –

+0

@AlexTartan, dostałem twój punkt widzenia. Ale używam MAX (status_id), aby uzyskać ostatni status dla tego zamówienia. –

+0

Chociaż nie jest to poprawne, możesz * użyć * SELECT distinct oo.order_id ... '. Lub spróbuj dołączyć do podsekcji 'table_order_status' już pogrupowanej według order_id, zamiast całej tabeli. Jeśli uda Ci się skonfigurować Fiddle SQL (http://sqlfiddle.com/), mógłbym spojrzeć na –

Odpowiedz

0

Powinieneś skupić się na pierwszej podselekcji na uzyskaniu wszystkich informacji o zamówieniu oprócz tego statusu, a następnie dołączyć informacje o statusie.

To może wyglądać następująco:

SELECT 
    order_with_status.order_id AS order_id, 
    order_with_status.amount AS amount, 
    order_with_status.`date` AS `date`, 
    order_with_status.quantity AS quantity, 
    order_with_status.`time` AS `time`, 
    tosv.value_description AS current_status  
FROM (
    /* Add maximum order status value to result set */ 
    SELECT 
     order.order_id AS order_id, 
     order.amount AS amount, 
     order.`date` AS `date`, 
     order.quantity AS quantity, 
     order.`time` AS `time`, 
     MAX(tos.status) AS current_status_id 
    FROM (
     /* Get rolled-up order information as start to result set */ 
     SELECT 
      o.order_id AS order_id, 
      SUM(od.product_sell_price * od.quantity) AS amount, 
      DATE_FORMAT(o.order_datetime, '%d/%m/%Y') AS `date`, 
      SUM(od.quantity) AS `quantity`, 
      TIME(o.order_datetime) AS `time` 
     FROM table_orders AS o 
     INNER JOIN table_order_details AS od 
      ON o.order_id = od.order_id 
     GROUP BY o.order_id 
    ) as order 
    INNER JOIN table_order_status AS tos 
     ON order.order_id = tos.order_id 
) as order_with_status 
INNER JOIN table_order_status_values AS tosv 
    ON order_with_status.current_status_id = tosv.value_id 

ORDER BY order_with_status.order_id DESC 

pamiętać, że sam schemat sprawia, że ​​jest to bardzo skomplikowane zapytania, które nie mogą wykonywać bardzo dobrze, jeśli trzeba regularnie robić to zapytanie w systemie. Jeśli wprowadziłeś prostą zmianę, aby przenieść pole identyfikatora statusu zamówienia do tabeli zamówień, możesz uprościć to znacznie (relegacja tabeli table_order_status do po prostu historii audytu zmian stanu, które nie są używane w ogóle w tym typie zapytania). Ma to sens logiczny, ponieważ wydaje się, że nie ma potrzeby pracy z historią zmian zamówienia, gdy próbuje się uzyskać po prostu dane o bieżącym zamówieniu.

W tym przypadku zapytanie może być tak proste, jak

SELECT 
    o.order_id AS order_id, 
    tosv.value_description AS current_status, 
    SUM(od.product_sell_price * od.quantity) AS amount, 
    DATE_FORMAT(o.order_datetime, '%d/%m/%Y') AS `date`, 
    SUM(od.quantity) AS quantity, 
    TIME(o.order_datetime) AS `time` 
FROM table_orders AS o 
INNER JOIN table_order_status_values AS tosv 
    ON o.order_status_id = tosv.value_id 
INNER JOIN table_order_details AS od 
    ON o.order_id = od.order_id 
GROUP BY o.order_id 
ORDER BY o.order_id DESC 

Można uprościć to dalej, jeśli chcesz umieścić opis stanu w tabeli zleceń w przeciwieństwie do ID (to byłoby wyeliminować dodatkowy stół dołącz, aby uzyskać opis).

Teraz, czy ta pozorna normalizacja ma sens dla twojego zastosowania, będzie w dużej mierze zależała od przypadków użycia z aplikacją. Jeśli na przykład nie uzyskujesz dostępu do danych kontrolnych w znacznym stopniu lub tylko chcesz przedstawić te dane w kontekście pojedynczego zamówienia, może to mieć sens.

2

Państwo problem jest w tej części:

SELECT s.order_id, SUM(OD.product_sell_price * OD.quantity) as amount, 
     DATE_FORMAT(o.order_datetime, '%d/%m/%Y') as date, SUM(OD.quantity) 
     as quantity, TIME(o.order_datetime) as time, MAX(status_id) as laststatus 
    FROM table_orders o 
    INNER JOIN table_order_details AS OD ON o.order_id = OD.order_id 
    INNER JOIN table_order_status s ON s.order_id = o.order_id 
    GROUP BY o.order_id 

Suma nie zwraca aktualną wartość, ponieważ się mnożona każdy przyłączyć.

Możesz to rozwiązać, wybierając opcję zamiast używać tylko kolumn.

(SELECT SUM(OD.product_sell_price * OD.quantity) FROM table_order_details as OD WHERE OD.order_id=o.order_id) as amount 

I do zastosowania ilość:

(SELECT SUM(OD.quantity) FROM table_order_details as OD WHERE OD.order_id=s.order_id) as quantity, 

więc ostateczna zapytania będą:

SELECT oo.order_id, oo.amount, oo.date, oo.quantity, oo.time, value_desc 
FROM 
(
     SELECT 
     s.order_id, 
     (SELECT SUM(OD.product_sell_price * OD.quantity) FROM table_order_details as OD WHERE OD.order_id=s.order_id) as amount, 
     DATE_FORMAT(o.order_datetime, '%d/%m/%Y') as date, 
     (SELECT SUM(OD.quantity) FROM table_order_details as OD WHERE OD.order_id=s.order_id) as quantity, 
     TIME(o.order_datetime) as time, MAX(status_id) as laststatus 
    FROM table_orders o 
    INNER JOIN table_order_status s ON s.order_id = o.order_id 
    GROUP BY o.order_id 
)oo 

INNER JOIN table_order_status_values ON value_id = laststatus 

order by order_id DESC 

I wyświetli:

1 200 12/12/2015 3 19:42:47 CONFIRIM 

edit - mam również usunięte

INNER JOIN table_order_details AS OD ON o.order_id = OD.order_id 

Nie ma potrzeby, aby była ona dołączyła w tym zapytaniu

2

Po pierwsze Twój SQL nie jest ważne, MySQL ignorować tego invlaid SQL, ale wynik nie będzie to, czego oczekiwano.

SELECT o.order_id, 
    oo.amt, 
    DATE_FORMAT(o.order_datetime, '%d/%m/%Y') date, 
    oo.qty, 
    TIME(o.order_datetime) time, 
    osv.value_desc 
FROM table_orders o, table_order_status_values osv, (
    SELECT order_id, sum(quantity) qty, sum(product_sell_price*quantity) amt 
    FROM table_order_details 
    GROUP BY 1 
) AS oo, (
    SELECT order_id, max(status_id) last_status 
    FROM table_order_status 
    GROUP BY 1 
) AS os 
WHERE o.order_id = os.order_id AND os.last_status = osv.status_id 
AND o.order_id = oo.order_id 
0

Sub-query użyłeś bez grupy, a suma/max:

SELECT s.order_id, OD.product_sell_price * OD.quantity as amount, 
     DATE_FORMAT(o.order_datetime, '%d/%m/%Y') as date, OD.quantity 
     as quantity, TIME(o.order_datetime) as time, status_id as laststatus 
    FROM table_orders o 
    INNER JOIN table_order_details AS OD ON o.order_id = OD.order_id 
    INNER JOIN table_order_status s ON s.order_id = o.order_id 

skutkowałoby:

1 20*1 2015:12:12 1 19:42:47 1 
1 20*1 2015:12:12 1 19:42:47 2 
1 90*2 2015:12:12 2 19:42:47 1 
1 90*2 2015:12:12 2 19:42:47 2 

Dodając SUM/MAX i grupy przez nią podaje dane wyjściowe podane w pytaniu:

1 400.00 12:12:2015 6 19:42:47 2 

Która jest poprawna zgodnie z zapytaniem, które napisałeś. Rozwiązaniem jest to, że powinieneś otrzymać MAX (status_id) osobno. więc użyć następującego zapytania:

SELECT oo.order_id, oo.amount, oo.date, oo.quantity, oo.time, value_desc 
FROM 
(
    SELECT s.order_id, SUM(OD.product_sell_price * OD.quantity) as amount, 
     DATE_FORMAT(o.order_datetime, '%d/%m/%Y') as date, SUM(OD.quantity) 
     as quantity, TIME(o.order_datetime) as time, MAX(select MAX(status_id) from table_order_status ts where ts.order_id = o.order_id group by ts.order_id) as laststatus 
    FROM table_orders o 
    INNER JOIN table_order_details AS OD ON o.order_id = OD.order_id 
    GROUP BY o.order_id 
)oo 

INNER JOIN table_order_status_values ON value_id = laststatus 

order by order_id DESC 

on użyje rzędów:

1 20*1 2015:12:12 1 19:42:47 2 
1 90*2 2015:12:12 2 19:42:47 2 

podając oczekiwany wynik:

1 200 2015:12:12 319:42:47 2 
Powiązane problemy