0

I have mysql table like this

| idx|  name  | year | month | value |
| 1  |  foo   | 2017 | 1     | bar1  |
| 2  |  foo   | 2017 | 2     | bar2  |
| 3  |  foo   | 2017 | 3     | bar3  |
| 4  |  foo   | 2017 | 4     | bar4  |

I want to query for grid table like this

| idy |  name  | year | month1  | month2 | month3 | month4 |
| 1   |  foo   | 2017 | bar1    | bar2   | bar3   | bar4   | 

how can do this, thanks alot

i mean query rows to one row, i want to fill table like this

<table>
    <tr>
       <th>id</th>
       <th>name</th>
       <th>year</th>
       <th>month1</th>
       <th>month2</th>
       <th>month3</th>
       <th>month4</th>
    </tr>
    <tr>
       <td><?php echo $row[id]; ?></td>
       <td><?php echo $row[name]; ?></td>
       <td><?php echo $row[year]; ?></td>
       <td><?php echo $row[month1]; ?></td>
       <td><?php echo $row[month2]; ?></td>
       <td><?php echo $row[month3]; ?></td>
       <td><?php echo $row[month4]; ?></td>
    </tr>
</table>
6
  • where is your query ? Commented Oct 2, 2017 at 14:53
  • like select * from table where name='foo' and year=2017 .....blablabla i don't know how to do that Commented Oct 2, 2017 at 14:55
  • 2
    That's all the query you need. Commented Oct 2, 2017 at 14:56
  • no sir, i just want to select for table like that Commented Oct 2, 2017 at 15:24
  • 1
    This transformation is called pivoting and this question has already been asked and answered here on SO several times. The two duplicate topics explain how to create a pivot table within MySQL. However, it may be more effective to do the pivoting within the application (in php in this particular case). Commented Oct 2, 2017 at 15:27

1 Answer 1

2

A couple ways you can accomplish what you need.

The first would be with a group by with a MAX condition.

SELECT 
    p.name, 
    p.`year`, 
    MAX(IF(p.`month` = 1, p.value, NULL)) AS month1, 
    MAX(IF(p.`month` = 2, p.value, NULL)) AS month2,
    MAX(IF(p.`month` = 3, p.value, NULL)) AS month3,
    MAX(IF(p.`month` = 4, p.value, NULL)) AS month4
FROM table_name AS p
GROUP BY p.name, p.`year`

Another approach would be with joins for each month you want to retrieve.

SELECT 
  p.name,
  p.`year`, 
  m1.value AS month1, 
  m2.value AS month2, 
  m3.value AS month3, 
  m4.value AS month4
FROM table_name AS p
LEFT JOIN table_name AS m1
ON m1.name = p.name AND m1.`year` = p.`year` AND m1.`month` = 1
LEFT JOIN table_name AS m2
ON m2.name = p.name AND m2.`year` = p.`year` AND m2.`month` = 2
LEFT JOIN table_name AS m3
ON m3.name = p.name AND m3.`year` = p.`year` AND m3.`month` = 3
LEFT JOIN table_name AS m4
ON m4.name = p.name AND m4.`year` = p.`year` AND m4.`month` = 4
#....
WHERE p.name = 'foo' AND p.`year` = 2017
GROUP BY p.name, p.`year`;

Demo: http://sqlfiddle.com/#!9/6de54a/3

Results of both would be the same, however your ID would no longer be relevant, as you're grouping the individual rows into a single row, so I will leave it to you on how you want to display the ID.


Alternatively you can use PHP to transpose the data, separating the display by using an array key of the name and year.

Demo: https://3v4l.org/KvCD5

//SELECT * FROM table_name WHERE name = 'foo' AND `year` = '2017';

$data = [];
foreach($rows as $row) {
  $key = $row['name'] . '_' . $row['year'];
  if(!isset($data[$key])){
     $data[$key] = array(
         'id' => $row['id'],
         'name' => $row['name'],
         'year' => $row['year']
    );
  }
  $data[$key]['month' . $row['month']] = $row['value'];
}

Result:

Array
(
    [foo_2017] => Array
        (
            [id] => 1
            [name] => foo
            [year] => 2017
            [month1] => bar1
            [month2] => bar2
            [month3] => bar3
            [month4] => bar4
        )

)

Then you would iterate over the transposed data.

<table>
    <tr>
       <th>id</th>
       <th>name</th>
       <th>year</th>
       <th>month1</th>
       <th>month2</th>
       <th>month3</th>
       <th>month4</th>
    </tr>
<?php foreach($data as $row) { ?>
    <tr>
       <td><?php echo $row['id']; ?></td>
       <td><?php echo $row['name']; ?></td>
       <td><?php echo $row['year']; ?></td>
       <td><?php echo $row['month1']; ?></td>
       <td><?php echo $row['month2']; ?></td>
       <td><?php echo $row['month3']; ?></td>
       <td><?php echo $row['month4']; ?></td>
    </tr>
<?php } ?>
</table>
Sign up to request clarification or add additional context in comments.

3 Comments

@fyrye thanks a lot you save me
@Shadow As many times as you have for specific use-cases. I answered the OP's specific use-case, which was both correct and helpful. where the question you marked as duplicate does not provide. GROUP BY id vs GROUP BY name, year Marking it as duplicate suffices to point others to similar answers, but this question may also apply to other use-cases.
Yeah, an if a user asks how to join two tables and there is no duplicate that show exactly those fields that the OP joins on, then there is a specific use case to answer the question again... This way none of the questions could be closed as duplicates.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.