Php 从一个 mysql 查询创建多个 csv 文件

Php to create multiple csv(s) files from one mysql query

更新 #1 我有一个 php 文件,其中包含创建多个 csv 文件的多个查询。 我想合并查询。

我的 mysql table 有 5 列:ID、货币、汇率、日期、临时时间

创建 table table 并插入一些记录

    CREATE TABLE IF NOT EXISTS `table` ( `id` INT NOT NULL AUTO_INCREMENT , `currency` VARCHAR(254) NOT NULL , `rate` FLOAT NOT NULL , `date` VARCHAR(254) NOT NULL , `temptime` DATE NOT NULL , PRIMARY KEY (`id`), UNIQUE `UNIQUE` (`currency`, `temptime`)) ENGINE = MyISAM;

INSERT INTO `table` 
(currency, rate, date, temptime)
VALUES 
('USD', '1.232', '1521212400', '2018-03-16'),
('USD', '1.258', '1521126000', '2018-03-15'),
('JPY', '133.82', '1521212400', '2018-03-16'),
('JPY', '131.88', '1521126000', '2018-03-15'),
('EUR', '1.99', '1521212400', '2018-03-16'),
('EUR', '1.85', '1521126000', '2018-03-15'),
('BRL', '1.6654', '1521212400', '2018-03-16'),
('BRL', '1.5498', '1521126000', '2018-03-15'),
('ZAR', '1.99654', '1521212400', '2018-03-16'),
('ZAR', '2.0198', '1521126000', '2018-03-15'),
('RUB', '19.9654', '1521212400', '2018-03-16'),
('RUB', '20.0198', '1521126000', '2018-03-15');

这些是我要为 "currency" 美元和欧元列合并的 2 个查询:

    $result = mysql_query("SELECT temptime, rate FROM `table` WHERE currency='USD' ORDER BY date asc"); 
if (!$result) die('Couldn\'t fetch records'); 
$num_fields = mysql_num_fields($result); 
$headers = array(); 
for ($i = 0; $i < $num_fields; $i++) 
{     
       $headers[] = mysql_field_name($result , $i); 
} 
$fp = fopen('csv/USD.csv', 'w'); 


if ($fp && $result) 
{     
       fputcsv($fp, $headers); 
       while ($row = mysql_fetch_row($result)) 
       {
          fputcsv($fp, array_values($row)); 
       }
} 

$result = mysql_query("SELECT temptime, rate FROM `table` WHERE currency='EUR' ORDER BY date asc"); 
if (!$result) die('Couldn\'t fetch records'); 
$num_fields = mysql_num_fields($result); 
$headers = array(); 
for ($i = 0; $i < $num_fields; $i++) 
{     
       $headers[] = mysql_field_name($result , $i); 
} 
$fp = fopen('csv/EUR.csv', 'w'); 


if ($fp && $result) 
{     
       fputcsv($fp, $headers); 
       while ($row = mysql_fetch_row($result)) 
       {
          fputcsv($fp, array_values($row)); 
       }
} 

谢谢

您可以使用每行中的货币字段来决定要写入哪个文件,我使用了一个文件句柄数组,因此您无需围绕哪个文件设置任何条件,只需使用货币作为索引即可文件句柄...

// Create an array of files, each associated with currency
$fp = array( 'EUR' => fopen('csv/EUR.csv', 'w'),
        'USD' => fopen('csv/USD.csv', 'w'));

$result = mysql_query("SELECT currency, temptime, rate FROM `table` ORDER BY date asc");
if (!$result) die("Couldn't fetch records");
$num_fields = mysql_num_fields($result);
$headers = array();
for ($i = 0; $i < $num_fields; $i++)
{
    $headers[] = mysql_field_name($result , $i);
}
// Write out headers to each file.
foreach ( $fp as $output )  {
    fputcsv($output, $headers);
}

while ($row = mysql_fetch_row($result))     {
    // Use first field to decide which file to write to.
    $currency = array_shift($row);
    fputcsv($fp[$currency], $row);
}
// Close all of the files.
foreach ( $fp as $output )  {
    fclose($output);
}

因为我没有你的数据库,所以我无法测试这个,但是如果你有任何问题,请告诉我。

也考虑不使用循环并直接从 MySQL 及其 SELECT ... INTO OUTFILELOAD DATA INFILE 的补充)导出到 CSV。

具体来说,在下面 PHP 中分别执行两个操作查询(一定要转义引号)。虽然没有合并,但这个过程应该是一个比多个循环更快的 read/write IO 过程。另外,您可以在不更改 csv 导出代码的情况下交换应用层(即使用 Python、Java)!

SELECT temptime, rate 
INTO OUTFILE '/path/to/csv/USD.csv'
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM `table` 
WHERE currency='USD' 
ORDER BY `date` asc;

SELECT temptime, rate 
INTO OUTFILE '/path/to/csv/EUR.csv'
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM `table` 
WHERE currency='EUR' 
ORDER BY `date` asc;

并且对于一个调用,都放在 MySQL 存储过程中:

DELIMITER $$
DROP PROCEDURE IF EXISTS export_csv$$

CREATE PROCEDURE export_csv
BEGIN
    -- SELECT ... INTO OUTFILE COMMANDS
END$$

DELIMITER ;

然后在PHP运行中加上one-liner(使用mysqliAPI):

$result = mysqli_query($conn, "CALL export_csv")

请注意:headers 未通过上述命令传递。使用需要类型转换的联合解决调整查询。而且 CSV 不存储类型或 unicodes 元数据,所以这里有问题。

SELECT 'temptime' as col1, 'rate' as col2
UNION ALL
SELECT CAST(temptime, CHAR(10) as col1, 
       CAST(ROUND(rate,4) AS CHAR(3)) as col2
INTO OUTFILE '/path/to/csv/USD.csv'
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM `table` 
WHERE currency='USD' ;