検査項目を月ごとに集計する php

AST ALT などの項目検査数を月ごとに集計します。

sqlite3 では月ごとの集計ができないので、sqlite 3 を mysql に書き換えてから集計します。

クエリ

2021 年に施行された検査を項目別に、月ごとに集計します。
クエリは以下のようになっています。


SELECT
	DATE_FORMAT(hizuke, '%Y-%m') as hizuke, koumokuNo, koumokuName,COUNT(*) as count
FROM
	kekka
WHERE
	'2020-12-31' < hizuke AND hizuke < '2022-01-01'
GROUP BY
	DATE_FORMAT(hizuke, '%Y-%m'), koumokuNo, koumokuName
ORDER BY
	hizuke, koumokuNo ;

php プログラム


<?php

class stats_koumoku{
	
	private $alldata ;
	private $allkoumoku ;
	private $tukiArr ;
	private $koumokuNoArr ;
	private $koumokuNamearr ;
	private $tableData;

	public function __construct()
	{
		require_once('../../dbinfo/mysqlinfo.php') ;
		$this -> alldata = array();
		$this -> allkoumoku = array();
		$this -> tukiArr = array();
		$this -> koumokuNoArr = array();
		$this -> koumokuNameArr = array();
		$this -> tableData = array();	
	}
	
	public function readData()
    {
		$alldata = $this -> alldata ;
		try{
			$dsn = 'mysql:host='.host.';dbname='.dbname.';charset=utf8';
			$pdo = new PDO ($dsn, username, password ,array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)); 
			$sql = "SELECT
				DATE_FORMAT(hizuke, '%Y-%m') as hizuke, koumokuNo, koumokuName,COUNT(*) as count
				FROM kekka
				WHERE '2020-12-31' < hizuke AND hizuke < '2022-01-01'
				GROUP BY DATE_FORMAT(hizuke, '%Y-%m'), koumokuNo, koumokuName
				ORDER BY hizuke, koumokuNo ;";	
			$stmt = $pdo->prepare($sql);
			$stmt->execute();	
			while($res = $stmt->fetch(PDO::FETCH_ASSOC)){
				$hizuke = $res['hizuke'] ;
				$allData[] = array( $res['hizuke'], $res['koumokuNo'], $res['koumokuName'], $res['count'] );
			}
			$this -> allkoumoku = $allData ;	
		}catch (PDOException $e){
			echo('Error:'.$e->getMessage());
			die();
		}	
	}

	public function tkArr()
    {
		$allkoumoku = $this -> allkoumoku ;
		$tukiArr = $this -> tukiArr ;
		$koumokuNoArr = $this -> koumokuNoArr ;	
		foreach( $allkoumoku as $eachline )
		{
			if( !in_array( $eachline[0], $tukiArr ) ){
				$tukiArr[] = $eachline[0] ;
			}
			if( !in_array( $eachline[1], $koumokuNoArr ) ){
				$koumokuNoArr[] = $eachline[1] ;
			}
		}	
		$this -> tukiArr = $tukiArr ;
		$this -> koumokuNoArr = $koumokuNoArr ;
	}

	public function initTbl()
	{
		$tableData = $this -> tableData ;
		$tukiArr = $this -> tukiArr ;
		$koumokuNoArr = $this -> koumokuNoArr ;
		$gyo = count($koumokuNoArr) ;
		$retu = count($tukiArr) ;
		for( $i=0; $i < $gyo; $i++) {
			for( $j=0; $j < $retu; $j++) {
				$tableData[$i][$j] = null ;
			}
		}
		$this -> tableData = $tableData ;
	}

	public function createSheet() 
	{
		$allkoumoku = $this -> allkoumoku ;
		$tukiArr = $this -> tukiArr ;
		$koumokuNoArr = $this -> koumokuNoArr ;
		$tableData = $this -> tableData ;
		foreach( $allkoumoku as $eachline ){
			$tuki = $eachline[0] ;
			$koumokuNo = $eachline[1] ;
			$eachData = $eachline[3] ;
			$xkey = array_search( $tuki, $tukiArr );
			$ykey = array_search( $koumokuNo, $koumokuNoArr );
			$tableData[$ykey][$xkey] = $eachData ;
		}
		$this -> tableData = $tableData ;
	}

	public function koumokuName()
	{
		$koumokuNameArr = $this -> koumokuNameArr ;
		try{
			$dsn = 'mysql:host=localhost;dbname=stats_lapis;charset=utf8';
			$pdo = new PDO ($dsn, username, password ,array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)); 
			$sql = "SELECT koumokuNo, koumokuName FROM koumokuMST ;";
			$stmt = $pdo->prepare($sql);
			$stmt->execute();
			while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
				$koumokuNameArr[] = array( $row['koumokuNo'], $row['koumokuName'] ) ;
			}
			$this -> koumokuNameArr = $koumokuNameArr ;
		}catch (PDOException $e){
			echo('Error:'.$e->getMessage());
			die();
		}
	}
	
	public function createTable()	
	{
		$tableData = $this -> tableData ;
		$tukiArr = $this -> tukiArr ;
		$koumokuNoArr = $this -> koumokuNoArr ;
		$koumokuNameArr = $this -> koumokuNameArr ;
		$lineNum = 0 ;
		$tbl = "<table class='datashow'>\n";
		//-----------------  一番上の行を追加 -- 年付きの行
		array_unshift( $tukiArr, "項目" ); // 項目のカラムを追加
		$header = "" ;
		foreach( $tukiArr as $key => $tuki )
		{
			if( $key === 0 )
			{
				$eh = $tuki ;
			}else{
				$eh = date( "Y-m", strtotime($tuki)) ;
			}
			$header .= "<th>$eh</th>" ;
		}
		$tbl .= "<tr>{$header}</tr>\n" ;
		//------------------  各データ行を追加
		foreach( $tableData as $rkey => $eachline )
		{
			$searchkey = array_search( $koumokuNoArr[$lineNum], array_column( $koumokuNameArr, 0));
			$koumokuName = $koumokuNameArr[$searchkey][1] ;
			$datas = "" ;
			foreach( $eachline as $ckey => $val )
			{
				$datas .= "<td class='value'>$val</td>";
			}
			$tbl .= "<tr><th class='koumoku'>$koumokuName</th>$datas</tr>\n" ;
			$lineNum++ ;
		}
		$tbl .= "</table>" ;
		echo "<div class='container'>{$tbl}</div>" ;
	}
}
//--------------------------------
$koumokust = new stats_koumoku() ;
$koumokust -> readData() ;
$koumokust -> tkArr() ;
$koumokust -> koumokuName() ;
$koumokust -> initTbl() ;
$koumokust -> createSheet() ;
$koumokust -> createTable() ;

?>

実行結果

実行すると以下のようになります。
実行時間は 3 秒程度。

外来・入院を区別する

検査科の希望では外来と入院を区別して欲しいとのこと。

ただ、外来・入院の区別は検査結果のテーブルにはなく、検査リストのテーブルにあるためそれら 2 つのテーブルをリレーションする必要があります。

リレーションすると集計にとても時間がかかるので、他の方法はないかいろいろと探したのですが、どうもダメで、結局リレーションで集計することにしました。

クエリは、


SELECT
    DATE_FORMAT(kekka.hizuke, '%Y-%m') AS hizuke, koumokuNo, koumokuName, Iraika, COUNT(*) AS count
FROM
	kekka
INNER JOIN 
	kensa
ON
	kekka.hizuke = kensa.hizuke AND kekka.uketukeNo = kensa.uketukeNo
WHERE
	? < kekka.hizuke AND kekka.hizuke < ? AND ( Iraika = '1' OR Iraika = '2' )
GROUP BY
	DATE_FORMAT(hizuke, '%Y-%m'), koumokuNo, koumokuName, Iraika
ORDER BY
    hizuke, koumokuNo, Iraika ;

実際のプログラムは、


<?php

class stats_koumoku{

	private $allkoumoku ;
	private $tukiArr ;
	private $koumokuNoArr ;
	private $koumokuNamearr ;
	private $tableData;
	
	public function __construct()
	{
		require_once('../../dbinfo/mysqlinfo.php') ;
		$this -> allkoumoku = array();
		$this -> tukiArr = array();
		$this -> koumokuNoArr = array();
		$this -> koumokuNameArr = array();
		$this -> tableData = array();		
	}
	
	public function readData( $startdate, $enddate )
	{		
		$alldata = [] ;
		try{
			$dsn = 'mysql:host=localhost;dbname=stats_lapis;charset=utf8';
			$pdo = new PDO ($dsn, username, password ,array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)); 
			$sql = "
				SELECT
    				DATE_FORMAT(kekka.hizuke, '%Y-%m') AS hizuke, koumokuNo, koumokuName, Iraika, COUNT(*) AS count
				FROM
					kekka
				INNER JOIN 
					kensa
				ON
					kekka.hizuke = kensa.hizuke AND kekka.uketukeNo = kensa.uketukeNo
				WHERE
					? < kekka.hizuke AND kekka.hizuke < ? AND ( Iraika = '1' OR Iraika = '2' )
				GROUP BY
					DATE_FORMAT(hizuke, '%Y-%m'), koumokuNo, koumokuName, Iraika
				ORDER BY
    				hizuke, koumokuNo, Iraika ;
				";	
			$stmt = $pdo -> prepare( $sql );
			$stmt->execute( array( $startdate, $enddate ) );	
			while($res = $stmt->fetch(PDO::FETCH_ASSOC))
			{
				$hizuke = $res['hizuke'] ;
				$allData[] = array( $res['hizuke'], $res['koumokuNo'], $res['koumokuName'], $res['Iraika'], $res['count'] );
			}
			$this -> allkoumoku = $allData ;	
		}catch (PDOException $e){
			echo('Error:'.$e->getMessage());
			die();
		}	
	}

	public function tkArr()
	{
		$allkoumoku = $this -> allkoumoku ;
		$tukiArr = $this -> tukiArr ;
		$koumokuNoArr = $this -> koumokuNoArr ;	
		foreach( $allkoumoku as $eachline )
		{
			if( !in_array( $eachline[0], $tukiArr ) )
			{
				$tukiArr[] = $eachline[0] ;
			}
			if( !in_array( $eachline[1], $koumokuNoArr ) )
			{
				$koumokuNoArr[] = $eachline[1] ;
			}
		}		
		$this -> tukiArr = $tukiArr ;
		$this -> koumokuNoArr = $koumokuNoArr ;
	}

	public function initTbl() //  最終的なテーブルを初期化しておく
	{
		$tableData = $this -> tableData ;
		$tukiArr = $this -> tukiArr ;
		$koumokuNoArr = $this -> koumokuNoArr ;
		$gyo = count($koumokuNoArr) ;
		$retu = count($tukiArr) * 2 ;
		for( $i=0; $i < $gyo; $i++) 
		{
			for( $j=0; $j < $retu; $j++) 
			{
				$tableData[$i][$j] = null ;
			}
		}
		$this -> tableData = $tableData ;
	}

	public function createSheet() 
	{
		$allkoumoku = $this -> allkoumoku ;
		$tukiArr = $this -> tukiArr ;
		$koumokuNoArr = $this -> koumokuNoArr ;
		$tableData = $this -> tableData ;
		foreach( $allkoumoku as $eachline )
		{
			$tuki = $eachline[0] ;
			$koumokuNo = $eachline[1] ;
			$iraika = $eachline[3] ;
			$eachData = $eachline[4] ;			
			$ykey = array_search( $koumokuNo, $koumokuNoArr );
			if( $iraika === '1') 
			{
				$xkey = array_search( $tuki, $tukiArr ) * 2 ;
			}else{
				$xkey = array_search( $tuki, $tukiArr ) * 2 + 1 ;
			}
			$tableData[$ykey][$xkey] = $eachData ;
		}
		$this -> tableData = $tableData ;
	}

	public function koumokuName()
	{
		$koumokuNameArr = $this -> koumokuNameArr ;
		try{
			$dsn = 'mysql:host=localhost;dbname=stats_lapis;charset=utf8';
			$pdo = new PDO ($dsn, username, password ,array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)); 
			$sql = "SELECT koumokuNo, koumokuName FROM koumokuMST ;";
			$stmt = $pdo->prepare($sql);
			$stmt->execute();
			while($row = $stmt->fetch(PDO::FETCH_ASSOC))
			{
				$koumokuNameArr[] = array( $row['koumokuNo'], $row['koumokuName'] ) ;
			}
			$this -> koumokuNameArr = $koumokuNameArr ;
		}catch (PDOException $e){
			echo('Error:'.$e->getMessage());
			die();
		}
	}
	
	public function createTable()	
	{
		$tableData = $this -> tableData ;
		$tukiArr = $this -> tukiArr ;
		$koumokuNoArr = $this -> koumokuNoArr ;
		$koumokuNameArr = $this -> koumokuNameArr ;
		$lineNum = 0 ;
		$tbl = "<table class='datashow'>\n";
		//-----------------  一番上の行を追加 -- 日付の行
		$header = "<th rowspan='2'>項目</th>" ;
		$subheader = "" ;
		foreach( $tukiArr as $key => $tuki )
		{
			if( $key === 0 )
			{
				$eh = $tuki ;
			}else{
				$eh = date( "Y-m", strtotime($tuki)) ;
			}
			$header .= "<th colspan='2'>$eh</th>" ;
			for( $i = 0 ; $i < 2 ; $i++ ) 
			{
				if( $i % 2 === 0 ) 
				{
					$subheader .= "<td class='nyugai'>入院</td>" ;
				}else{
					$subheader .= "<td class='nyugai'>外来</td>" ;
				}
			}
		}
		$tbl .= "<tr>{$header}</tr><br>$subheader\n" ;
		//------------------  各データ行を追加
		foreach( $tableData as $rkey => $eachline )
		{
			$searchkey = array_search( $koumokuNoArr[$lineNum], array_column( $koumokuNameArr, 0));
			$koumokuName = $koumokuNameArr[$searchkey][1] ;
			$datas = "" ;
			foreach( $eachline as $ckey => $val )
			{
				$datas .= "<td class='val'>$val</td>";
			}
			$tbl .= "<tr><th class='koumoku'>$koumokuName</th>$datas</tr>\n" ;
			$lineNum++ ;
		}
		$tbl .= "</table>" ;
		echo "<div class='container'>{$tbl}</div>" ;
	}
}

//----------------------------------------------
$year = $_POST['year'] ;
$newyeardate = $year."-01-01" ;
$startdate = date('Y-m-d', strtotime('-1 day', strtotime( $newyeardate )));
$enddate = date('Y-m-d', strtotime('+1 year', strtotime( $newyeardate )));

$koumokust = new stats_koumoku() ;
$koumokust -> readData( $startdate, $enddate ) ;
$koumokust -> tkArr() ;
$koumokust -> koumokuName() ;
$koumokust -> initTbl() ;
$koumokust -> createSheet() ;
$koumokust -> createTable() ;

このプログラムに「2019」のような西暦年を外から与えます。

実行すると、

実行時間は、20 - 30 秒です。