mysql counting rows with loop

前端 未结 3 962
旧巷少年郎
旧巷少年郎 2021-01-25 07:31

I have the following table:

+-------------+--------------+ 
| product     | purchased    |
+-------------+--------------+ 
| Hammer      |   |
|         


        
相关标签:
3条回答
  • 2021-01-25 07:57

    What you need to work with is whether the warranty is still valid or expired and the warranty date, so you first need to build a table that reflects that:

    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
    ;
    

    That would get you something like that:

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

    Then use aggregate functions to filter and sum up the information you're looking for:

    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
                      , affffdate( 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 |
    +---------+-------+---------+---------------------+
    
    0 讨论(0)
  • 2021-01-25 08:01

    Here's the answer I posted in your 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 讨论(0)
  • 2021-01-25 08:15

    Better normalization would speed up this query tremendously, but here's an example to work from:

    First, you need to start with your base query, the one that will drive the results. In this case, it's a list of all the products in your table:

    SELECT DISTINCT product
    FROM   productWarranty
    

    The above query creates a sort of "temp" table that we can base our queries on. If you have a separate, normalized product table then that would be much better.

    The rest of the columns can simply be subqueries driven by your base table:

    Total count:

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

    Total valid warranties:

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

    Total expired warranties:

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

    Last purchase date:

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

    Now to combine all of these into a single query:

    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 讨论(0)
提交回复
热议问题