1

我有下表:

+-------------+--------------+ 
| 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       |
+-------------+--------------+----------------+------------------+------------------+

我尝试为此示例创建查询,但我不知道如何循环每个产品的结果以计算有效保修等。这就是我目前所拥有的:

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

我不知道如何编写子查询,因为我需要使用 WHERE product = Hammer 之类的东西。但是我怎样才能告诉 sql 为每个产品循环呢?

4

3 回答 3

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 |
+---------+-------+---------+---------------------+
于 2013-10-21T15:04:21.117 回答
2

更好的规范化会极大地加速这个查询,但这里有一个例子:

首先,您需要从基本查询开始,即驱动结果的查询。在这种情况下,它是表中所有产品的列表:

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
于 2013-10-21T14:56:05.867 回答
0

这是我在您的另一个问题中发布的答案

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
于 2013-10-25T08:24:15.790 回答