Comparing data using year in query

I have data and it is logged every year, I am trying to compare data for two years (last year and current year) in one mysql query

Below are my tables

Expenditures

| cid   |   items   |
| 1     |   A       |
| 2     |   B       |

      

The cost

| cid   | amount    |   year    |
|  1    |   10      |   1       |
|  1    |   20      |   2       |
|  1    |   30      |   1       |

      

This is the result I expect when I want to compare year 1 and year 2. Year 1 is the last year and year 2 is the current year.

results

items   |   pastCost    |   currentCost |
 A      |     10        |       20      |
 A      |     30        |       0       |

      

However, the query below is what I used, gives a strange answer.

SELECT 
    IFNULL(ps.`amount`, '0') as  pastCost
    IFNULL(cs.`amount`, '0') as currentCost
FROM
    `Cost Items` b

LEFT JOIN 

    `Cost` ps 
ON 
    b.cID=ps.cID 
        AND 
    ps.Year = 1

LEFT JOIN 
    `Cost` cu 
ON 
    b.cID=cu.cID 
        AND 
    cu.Year =2

      

This is the result I am getting from my request

items   |   pastCost    |   currentCost |
 A      |     10        |       20      |
 A      |     30        |       20      |

      

Please, what am I doing wrong? Thanks for the help.

+3


source to share


1 answer


I am missing something about your request; the displayed SQL text cannot give a result.

There is no source for the column in the SELECT list items

, and there is no table aliased like cs

. (It looks like the expression in the SELECT list should be cu.amount

In addition, the returned results look exactly as we expected. Every row returned from year=2

is matched against every row returned from year=1

. If year=1

there were three lines for year=1

and two lines for year=2

, we would get six lines back ... each line for year=1

"matched" each line for year=2

.

If (cid, year)

tuple was UNIQUE in Cost

then this query will return a result similar to expected.

  SELECT b.items
       , IFNULL(ps.amount, '0') AS pastCost
       , IFNULL(cu.amount, '0') AS currentCost
    FROM `Cost Items` b
    LEFT
    JOIN `Cost` ps
      ON ps.cid  = b.cid 
     AND ps.Year = 1
    LEFT
    JOIN `Cost` cu 
      ON cu.cid  = b.cid 
     AND cu.Year = 2

      

Since it is (cid, year)

not unique, you need an extra column to "match" one row for year=1

with one row for year=2

.

Without any other column in the table, we can use the inline view to generate the value. I can illustrate how we can get MySQL to return a result set like the one you are showing in one way that can be done, but I don't think this is really a solution to whatever problem you are trying to solve:

  SELECT b.items
       , IFNULL(MAX(IF(a.year=1,a.amount,NULL)),0) AS pastCost
       , IFNULL(MAX(IF(a.year=2,a.amount,NULL)),0) AS currentCost
    FROM `Cost Items` b
    LEFT
    JOIN ( SELECT @rn := IF(c.cid=@p_cid AND c.year=@p_year,@rn+1,1) AS `rn` 
                , @p_cid := c.cid AS `cid`
                , @p_year := c.year AS `year`
                , c.amount
             FROM (SELECT @p_cid := NULL, @p_year := NULL, @rn := 0) i
             JOIN `Cost` c
               ON c.year IN (1,2)
            ORDER BY c.cid, c.year, c.amount
         ) a
      ON a.cid = b.cid
   GROUP
      BY b.cid
       , a.rn

      

A query like this will return a result set similar to the one you expect. But then again, I strongly suspect that these are not actually the results you are really looking for.



EDIT

OP leaves a comment with a vaguely vague message about the observed behavior: "the above solution doesn't work "

Ok then check it out ... create a SQL Fiddle with some tables so we can test the query ...

The SQL script is here http://sqlfiddle.com/#!9/e3d7e/1

create table `Cost Items` (cid int unsigned, items varchar(5));
insert into `Cost Items` (cid, items) values (1,'A'),(2,'B');
create table `Cost` (cid int unsigned, amount int, year int);
insert into `Cost` (cid, amount, year) VALUES (1,10,1),(1,20,2),(1,30,1);

      

And when we run the request, we get a syntax error. Where there is no list in the SELECT list, it is easy enough to commit.

  SELECT b.items
       , IFNULL(MAX(IF(a.year=1,a.amount,NULL)),0) AS pastCost
       , IFNULL(MAX(IF(a.year=2,a.amount,NULL)),0) AS currentCost
    FROM `Cost Items` b
    LEFT
    JOIN ( SELECT @rn := IF(c.cid=@p_cid AND c.year=@p_year,@rn+1,1) AS `rn` 
                , @p_cid := c.cid AS `cid`
                , @p_year := c.year AS `year`
                , c.amount
             FROM (SELECT @p_cid := NULL, @p_year := NULL, @rn := 0) i
             JOIN `Cost` c
               ON c.year IN (1,2)
            ORDER BY c.cid, c.year, c.amount
         ) a
      ON a.cid = b.cid
   GROUP
      BY b.cid
       , a.rn

      

Return:

  items   pastCost  currentCost  
  ------  --------  -----------
  A             10           20
  A             30            0
  B              0            0

      

+2


source







All Articles