2

不确定要搜索什么,所以这可能是一个重复的问题。我有一个 mysql 数据库,其中有一个名为 software 的表。软件表由以下字段组成:

id (auto_increment)
computer_name
software_name
software_version
install_date

每次安装、升级或恢复到以前版本的软件时,都会在表中创建一个新条目。

我正在尝试使用 php 构建一个看起来像这样的表:

.---------------------------------------------------.
|            | software x | software y | software z |
|---------------------------------------------------|
| computer a | ver 1.0    |            | ver 1.2    |
|---------------------------------------------------|
| computer b |            | ver 2.1    |            |
|---------------------------------------------------|
| computer c | ver 1.3    | ver 1.1    |            |
'---------------------------------------------------'

从这样的数据:

computer_name  |  software_name  |  software_version  |  install_date
----------------------------------------------------------------------
computer a     |  software x     |  ver 1.1           |  [10 days ago]
computer a     |  software x     |  ver 1.0           |  [2 days ago]
computer a     |  software z     |  ver 1.1           |  [20 days ago]
computer a     |  software z     |  ver 1.2           |  [5 days ago]

install_date将是一个实际日期,为方便起见,在 [X 天前] 中输入。

该表将显示每台计算机上安装的每个软件的最新版本,每个唯一的计算机条目只有一行,每个唯一的软件条目只有一列。

这可能与单个 MySQL 表有关吗?实现这一目标的最佳方法是什么?我正在将 PHP 和 MySQL 与 codeigniter 一起使用。

更新:

通过查看可能的重复问题,我能够准备此查询:

SET @sql = NULL;

SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'MAX(IF(software_name = ''',
      software_name,
      ''', software_version, NULL)) AS ',
      replace(software_name, ' ', '_')
    )
  ) INTO @sql 
FROM 
  software;

SET @sql = CONCAT('SELECT computer_name, ', @sql, ' FROM software GROUP BY computer_name');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

它以我正在寻找的格式生成结果,但是它不是通过最新版本获取版本,install_date而是通过找到的最大版本号获取。如何修改上述内容以获取具有最新关联的版本install_date

4

2 回答 2

1

一项艰苦的工作,但我得到了一个可以实现结果的查询!

您在数据库方面需要的CROSS JOIN是能够针对所有不同的软件列出所有不同的计算机,然后过滤所需的software_version.

我用这个查询做到了:

SELECT 
  b.computer_name, 
  a.software_name, 
  MAX(IF(b.software_name = a.software_name AND b.id = a.id, a.software_version, '')) AS software_version 
FROM 
  software AS a, 
  software AS b 
GROUP BY 
  b.computer_name, 
  a.software_name 
ORDER BY 
  b.computer_name ASC, 
  a.software_name ASC, 
  software_version DESC;

我的表数据有这些值:

------ ---------------- --------------- -------------- ---- ---------
| 编号 | 计算机名 | 软件名称 | 软件版本 | 安装日期 |
 --------------- ------ --------------- -------------- ---- ---------
| 1 | 电脑a | 软件 x | 1.1 版 | 2013-03-27 15:58:17 |
| 2 | 电脑a | 软件 x | 版本 1.0 | 2013-03-27 15:58:20 |
| 3 | 电脑a | 软件z | 1.3 版 | 2013-03-27 15:58:24 |
| 4 | 电脑b | 软件z | 1.4 版 | 2013-03-27 15:58:30 |
| 5 | 电脑b | 软件z | 1.2 版 | 2013-03-27 15:58:45 |
| 6 | 电脑c | 软件 x | 1.5 版 | 2013-03-27 15:58:51 |
| 7 | 电脑c | 软件y | 1.7 版 | 2013-03-27 15:58:58 |
 --------------- ------ --------------- -------------- ---- ---------

这是我的输出:

------------ ------------ ------------------
| 电脑 | 软件 | 软件版本 |
 ------------ ------------ ------------------
| 电脑a | 软件 x | 1.1 版 |
| 电脑a | 软件y | |
| 电脑a | 软件z | 1.3 版 |
| 电脑b | 软件 x | |
| 电脑b | 软件y | |
| 电脑b | 软件z | 1.4 版 |
| 电脑c | 软件 x | 1.5 版 |
| 电脑c | 软件y | 1.7 版 |
| 电脑c | 软件z | |
 ------------ ------------ ------------------

在你的 PHP 代码中你应该做这样的事情(正如我所知道的纯 PHP - 我没有测试下面的 PHP 代码,这不是最好的编码方式......但我认为它会起作用,它基于我的查询输出):

<?php
  $sql = 'SELECT ...';  // put the query here
  $result = mysql_query($sql);

  if( $result and mysql_num_rows($result))
  {
    $num_rows = mysql_num_rows($result);

    $versions = array();
    while ($row = mysql_fetch_assoc($result))
      $versions[] = $row;

    // Here we'll count how much softwares we have 
    $software_count = -1;
    $first_computer = $versions[0]['computer_name'];

    while( $versions[++$software_count]['computer_name'] == $first_computer );

    echo "<table>". 
           "<thead>". 
             "<tr>". 
               "<th></th>";

    // Here we'll print the softwares names as our table headers
    for($i = 0; $i < $software_count; $i++)
      echo "<th>". $versions[$i]['software_name'] . "</th>";

    echo     "</tr>". 
           "</thead>". 
           "<tbody>";

    // Here we'll print the data
    while($num_rows)
    {
      echo   "<tr>". 
               "<td style='font-weight: bold;'>". 
                 $versions[$i]["computer_name"] .
               "</td>";

      for($i = 0; $i < $software_count; $i++)
        echo   "<td>". $versions[$i]["software_version"] . "</td>";

      echo   "</tr>";

      $num_rows -= $software_count;
    }

    echo   "</tbody>".  
         "</table>";

  mysql_free_result($result);

?>

一些工作,但我希望它可以帮助你,我希望我的 PHP 代码工作正常!祝你好运!

于 2013-03-27T22:59:15.370 回答
0

像这样的东西应该可以工作(比使用 distinct 快得多)。

select computer_name,software_name,software_version,install_date from table group by software_name order by computer_name,install_date DESC

这样您仍然可以显示每台计算机上的所有软件。

如果您想将条目限制为每台计算机安装的最新软件,您可以使用:

select computer_name,software_name,software_version,install_date from table group by computer_name,software_name order by computer_name,install_date DESC
于 2013-03-27T20:07:31.377 回答