2

何を検索すればよいかわからないため、これは重複した質問である可能性があります。ソフトウェアと呼ばれる単一のテーブルを持つmysqlデータベースがあります。ソフトウェア テーブルは、次のフィールドで構成されます。

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 日前] を挿入した実際の日付になります。

テーブルには、各コンピューターにインストールされている各ソフトウェアの最新バージョンが表示されます。一意のコンピューター エントリごとに 1 つの行と、一意のソフトウェア エントリごとに 1 つの列のみが表示されます。

単一の 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;

私のテーブルデータには次の値がありました:

------ --------------- --------------- -------------- ---- ----------------------
| | ID | コンピューター名 | ソフトウェア名 | software_version | インストール日 |
 --------------- ------ --------------- -------------- ---- ----------------------
| | 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 |
 --------------- ------ --------------- -------------- ---- ----------------------

そして、これが私の出力でした:

------------ ------------ ------------------
| | コンピューター | ソフトウェア | software_version |
 ------------ ------------ ------------------
| | コンピューター 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 に答える