2013-10-21 37 views
1

MySQL的計數行我有如下表:與循環

+-------------+--------------+ 
| product  | purchased | 
+-------------+--------------+ 
| Hammer  | <timestamp> | 
| Nipper  | <timestamp> | 
| Saw   | <timestamp> | 
| Nipper  | <timestamp> | 
| Hammer  | <timestamp> | 
| Hammer  | <timestamp> | 
| Saw   | <timestamp> | 
| Saw   | <timestamp> | 
| Saw   | <timestamp> | 
+-------------+--------------+ 

我希望看到一個關於這些產品的保修狀態摘要。保修期應從購買日起5年。因此,今天的日期應該有可能檢查產品是否在保修期內(基於購買日期)。此外,我想現在當最後買的產品將超出保修期。下面是一個示例表:

+-------------+--------------+----------------+------------------+------------------+ 
| product  | count  | warranty valid | warranty expired | last p. warranty | 
+-------------+--------------+----------------+------------------+------------------+ 
| Hammer  | 3   | 1    | 2    | 10.03.2015  | 
| Nipper  | 2   | 2    | -    | 01.01.2014  | 
| Saw   | 4   | 1    | 3    | 02.12.2013  | 
+-------------+--------------+----------------+------------------+------------------+ 

我試圖創建這個例子的查詢,但我不知道每個產品的結果如何循環計數有效warrantys等。這就是我目前的樣子:

SELECT 
    product, 
    date_format(from_unixtime(purchased), '%d.%m.%Y') AS purchaseDate, 
    date_format(date_add(from_unixtime(purchased), INTERVAL 5 YEAR), '%d.%m.%Y') AS warrantyEnd, 
    (
     SELECT 
      COUNT(product) 
     FROM 
      productWarranty 
    ) AS count 
FROM 
    productWarranty s 
GROUP BY 
    product 

我不知道怎麼寫的子查詢,因爲我需要用的東西等,其中產品=錘。但是,我怎麼能告訴sql來循環每一個產品?

回答

1

這是我張貼在您other question

SELECT p2c.pid AS productNumber, 
     p.name AS productName, 
     COUNT(*) AS registered, 
     SUM(date_add(from_unixtime(purchased), INTERVAL 5 YEAR) >= CURDATE()) AS inWarranty, 
     SUM(date_add(from_unixtime(purchased), INTERVAL 5 YEAR) < CURDATE()) AS outOfWarranty, 
     DATE_FORMAT(MAX(from_unixtime(purchased)), '%d.%m.%Y') AS lastPurchased, 
     DATE_FORMAT(date_add(MAX(from_unixtime(purchased)), INTERVAL 5 YEAR), '%d.%m.%Y') AS warrantyUntil 
FROM products2customers p2c 
JOIN products p ON p.id = p2c.pid 
GROUP BY p2c.pid 
ORDER BY inWarranty DESC 
+0

再次感謝Barmar先生。 :)希望在未來的問題中見到你。 ;-) 祝你今天愉快。 – emjay

+0

我知道OP要求您在此發佈此信息,但您的回答並未回答所述問題(沒有提及聯結)。雷諾的本質與你的相同,但更適合於這個特定的問題。 – JDB

1

更好normalization將大大加快這一查詢,但這裏有一個例子從工作:

首先,你需要啓動你的基本查詢,一個將推動的結果。在這種情況下,它的所有產品在表中列出:

SELECT DISTINCT product 
FROM productWarranty 

上面的語句創建一種「臨時」表中,我們可以立足於我們的查詢。如果你有一個單獨的,規範化的產品表,那會更好。

列的其餘部分可以簡單地子查詢的基表驅動:

總計數:

SELECT COUNT(*) 
FROM productWarranty 
WHERE product = 'Hammer' 

總有效保證:

SELECT COUNT(*) 
FROM productWarranty 
WHERE product = 'Hammer' 
    AND purchased >= <warranty cut-off date> 

總到期擔保:

SELECT COUNT(*) 
FROM productWarranty 
WHERE product = 'Hammer' 
    AND purchased < <warranty cut-off date> 

最後一次購買日期:

SELECT MAX(purchased) 
FROM productWarranty 
WHERE product = 'Hammer' 

我們所有的這些組合成一個單一的查詢:

SELECT Base.product 
    , (
      SELECT COUNT(*) 
      FROM productWarranty 
      WHERE product = Base.product 
     ) AS TotalCount 
    , (
      SELECT COUNT(*) 
      FROM productWarranty 
      WHERE product = Base.product 
       AND date_add(from_unixtime(purchased), INTERVAL 5 YEAR) >= CURDATE() 
     ) AS ValidWarrantyCount 
    , ( 
      SELECT COUNT(*) 
      FROM productWarranty 
      WHERE product = Base.product 
       AND date_add(from_unixtime(purchased), INTERVAL 5 YEAR) < CURDATE() 
     ) AS ExpiredWarrantyCount 
    , (
      SELECT MAX(purchased) 
      FROM productWarranty 
      WHERE product = Base.product 
     ) AS LastPurchased 
FROM (
      SELECT DISTINCT product 
      FROM productWarranty 
     ) AS Base 
+0

嗨了答案,首先感謝您的解決方案。它效果很好。我試着添加JOIN commant,因爲我希望將公司名稱添加到此表中。但它不起作用。 : - /我試圖將它添加到基本查詢沒有成功。有任何想法嗎? – emjay

+0

@emjay - 我想你可以找到很多關於如何使用JOIN的例子([this](http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins .html),例如或[this](http://www.techonthenet.com/sql/joins.php))。但是,如果你還在掙扎,請發佈一個新問題。堆棧溢出不是留言板。 – JDB

+0

好吧,我做了一個SQL小提琴,所以我真的應該提出一個新的問題?因爲這只是關於使用連接來擴展查詢。我試過了,但它不起作用。我不知道該把它放在哪裏,我想在基本查詢中,但這不起作用。 (http://sqlfiddle.com/#!2/60396/1) – emjay

3

你需要使用的是什麼保修是否仍然有效或過期,保修日期,所以你首先需要建立一個反映了一個表:

select product 
     , IF(warranty >= NOW(), 1, 0) as valid 
     , IF(warranty < NOW(), 1, 0) as expired 
     , warranty as last 
from  (
      select product 
       , ADDDATE(purchased, INTERVAL 5 YEAR) as warranty 
      from  productWarranty 
     ) w 
group by product 
; 

這將讓你類似的東西:

+---------+-------+---------+---------------------+ 
| product | valid | expired | warranty   | 
+---------+-------+---------+---------------------+ 
| Hammer |  1 |  0 | 2017-01-01 00:00:00 | 
| Nipper |  1 |  0 | 2017-01-01 00:00:00 | 
| Nipper |  1 |  0 | 2017-01-01 00:00:00 | 
| Nipper |  1 |  0 | 2017-01-01 00:00:00 | 
| Saw  |  1 |  0 | 2017-01-01 00:00:00 | 
| Saw  |  0 |  1 | 2011-01-01 00:00:00 | 
| Saw  |  1 |  0 | 2017-01-01 00:00:00 | 
| Saw  |  1 |  0 | 2017-01-01 00:00:00 | 
+---------+-------+---------+---------------------+ 

然後使用聚合函數來篩選和總結你正在尋找的信息:

select product 
     , SUM(IF(warranty >= NOW(), 1, 0)) as valid 
     , SUM(IF(warranty < NOW(), 1, 0)) as expired 
     , MAX(warranty) as last 
from  (
      select product 
        , adddate(purchased, interval 5 year) as warranty 
      from productWarranty 
     ) w 
group by product 
; 
+---------+-------+---------+---------------------+ 
| product | valid | expired | last    | 
+---------+-------+---------+---------------------+ 
| Hammer |  1 |  0 | 2017-01-01 00:00:00 | 
| Nipper |  3 |  0 | 2017-01-01 00:00:00 | 
| Saw  |  3 |  1 | 2017-01-01 00:00:00 | 
+---------+-------+---------+---------------------+