2012-01-16 62 views
1

我正在嘗試製作一個可打印頁面,其中有指定製造商的所有銷售,列出所有產品之間的指定日期。如果沒有發生過任何銷售,它應該顯示0加入表格並用指定值替換空值

的表格

// Manufacturer table 
// mid, manufacturer 
// Products table 
// pid, product, ref_manufacturer_id 
// Orders table 
// oid, orderPrice, orderDateTime, ref_product_id 

而且其工作方式查詢(無日期限制)

SELECT prod.product, COALESCE(COUNT(pord.oid),0) AS orderCount, 
COALESCE(SUM(pord.orderPrice),0) AS orderSum 
FROM product_manufacturer AS manu 
JOIN product_list AS prod ON prod.ref_manufacturer_id = manu.mid 
LEFT JOIN product_orders AS pord ON pord.ref_product_id = prod.pid 
WHERE manu.mid = :manu_id 
GROUP BY prod.product; 

但只要我加入到WHERE語法

WHERE manu.mid = :manu_id AND DATE(pord.orderDateTime) BETWEEN :orders_start AND :orders_end 

我正在使用PHP PDO連接並驗證manu_id是int並且orders_start/end被轉換爲MySQL日期格式。

但是我試圖找出的問題是什麼導致了這個問題,當我添加日期限制時,每個沒有訂購的產品都不會顯示在輸出上?在創建表

CREATE TABLE product_list (
    pid bigint(20) unsigned NOT NULL AUTO_INCREMENT, 
    product varchar(255) NOT NULL, 
    ref_manufacturer_id bigint(20) unsigned NOT NULL, 
    PRIMARY KEY (pid), 
    KEY ref_manufacturer_id (ref_manufacturer_id) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; 

CREATE TABLE product_manufacturer (
    mid bigint(20) unsigned NOT NULL AUTO_INCREMENT, 
    manufacturer varchar(255) NOT NULL, 
    PRIMARY KEY (mid), 
    UNIQUE KEY manufacturer (manufacturer) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; 

CREATE TABLE product_orders (
    oid bigint(20) unsigned NOT NULL AUTO_INCREMENT, 
    orderPrice float(10,2) NOT NULL, 
    orderDatetime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    red_product_id bigint(20) unsigned NOT NULL, 
    PRIMARY KEY (oid), 
    KEY red_product_id (red_product_id) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; 

回答

2

你需要的是對orderDateTime標準移動到連接語句代替where子句,如:

SELECT prod.product, COALESCE(COUNT(pord.oid),0) AS orderCount, 
     COALESCE(SUM(pord.orderPrice),0) AS orderSum 
FROM product_manufacturer AS manu 
JOIN product_list AS prod ON prod.ref_manufacturer_id = manu.mid 
LEFT JOIN product_orders AS pord 
      ON pord.ref_product_id = prod.pid 
      AND DATE(pord.orderDateTime) BETWEEN :orders_start AND :orders_end 
WHERE manu.mid = :manu_id 
GROUP BY prod.product; 

它不WHERE子句中工作的原因是因爲NULL值從外返回加入。當product_orders沒有一行出現在產品中時,外部聯接會爲日期字段orderDateTime返回NULL,並且該行將被過濾掉,因爲NULL不等於任何內容。

+0

比MichałPowaga設定的簡單得多。這次真是萬分感謝。 – Gurnarok 2012-01-16 08:13:21

+0

你可以(或應)BETWEEN取代'DATE(pord.orderDateTime):orders_start AND:orders_end'用'(pord.orderDateTime> =:orders_start)AND(pord.orderDateTime 2012-01-16 14:25:46

+0

(我猜這兩個參數是日期)。 – 2012-01-16 14:28:52

0

SQL試試這個在where子句。

WHERE manu.mid = :manu_id AND (DATE(pord.orderDateTime) BETWEEN :orders_start AND :orders_end) 

它可能讀取第二個AND函數作爲另一個where子句,該語句應該返回true。只是一個預感。讓我知道這是否有竅門。

+0

沒有工作,仍然繼續只顯示那些日期之間有訂單的產品。並忽略那些沒有的。 – Gurnarok 2012-01-16 07:34:42

+0

也許是因爲我們的where子句定義日期應該在訂單開始和訂單結束之內。它應該真的忽視那些其他事實。請解釋你想做什麼。 – Nathan 2012-01-16 07:38:11

+0

我想顯示特定製造商的所有產品和指定日期之間的產品訂單,其中製造商是指定的。 – Gurnarok 2012-01-16 07:42:45

0

我不知道你的特定系統是如何工作的,但它可能是orderDateTime沒有設置(即,NULL或其他),直到該產品訂購。你可能也想嘗試:

WHERE manu.mid = :manu_id AND ((DATE(pord.orderDateTime) BETWEEN :orders_start AND :orders_end) OR pord.orderDateTime=NULL)

如果不是這種情況,你可以給你的時候它要的是沒有顯示出來的東西orderDateTime值的例子嗎?

2

嘗試:

SELECT p.product, 
    COALESCE(o.orderCount, 0) as orderCount, 
    COALESCE(o.orderSum,0) AS orderSum 
FROM product_manufacturer AS m 
JOIN product_list AS p ON p.ref_manufacturer_id = m.mid 
LEFT JOIN (
    SELECT ref_product_id as pid, COUNT(oid) AS orderCount, SUM(orderPrice) AS orderSum 
    FROM product_orders 
    WHERE DATE(orderDateTime) BETWEEN :orders_start AND :orders_end 
    GROUP BY ref_product_id 
) AS o ON p.pid = o.pid 
WHERE m.mid = :manu_id 

編輯:ypercube評論後更正。

+0

甜,這個按需運作。非常感謝:) – Gurnarok 2012-01-16 08:10:35

+0

您只需要子查詢中的'product_orders',而不是'product_list'。 – 2012-01-16 14:33:00

+0

@ypercube好點!糾正。 – 2012-01-16 15:12:09