这可以在MySQL查询中完成,还是需要在PHP中完成? (服务器端)

时间:2017-07-24 20:44:42

标签: php mysql

我有一张桌子:

#!perl

# originally part of project:Chi_Flexibles_Sys

#########################################################################################################################################
# README:


# Copyright (C) -------------------,  - All Rights Reserved
# Proprietary Software, All Use Must Be Licensed.
# This software is protected by U.S. Copyright Law and International Treaties. Unauthorized use, duplication, reverse engineering,
# any form of redistribution, or use in part or in whole other than by prior, express, printed and signed license for use is strictly prohibited.
# If you have received this file in error, please notify copyright holder and destroy this and any other copies
# as instructed.

# Copyright (c) 2016,-------------------
# Please donot remove and/or modify this copyright notice from the script without permission from the copyright holder.

#########################################################################################################################################

my $dir='C:\Users\USERNAME\Documents\Materials Studio Projects\2016-October-nanoreactor\Dimers Files\Documents\Case_5_(D)\Blends\AB\A2 Blends Mixing\Lowest energies'; #put in the current directory, because cwd() doesn't work

my $monomer1 = 'A2';
my $monomer2 = 'B2';

my $outfile1 = "$dir\\$monomer1 $monomer1.txt";
my $outfile2 = "$dir\\$monomer1 $monomer2.txt";
my $outfile3 = "$dir\\$monomer2 $monomer2.txt";

my $forcefield = "Dreiding";

(例如,这是为了减少字段数)。

我最初需要将每个'space x'分组(即:space1.x,space2.x,space3.x)分解为自己的ROWS(即使所有数据都在1个记录/行中)

  

id |第一个|最后|机构|地址| space1_1_value |   space1_2_value |协议

如果space2_1_value中有值,则:

  

id |第一个|最后|机构|地址| space2_1_value |   space2_2_value |协议

如果space3_1_value中有值,则:

  

id |第一个|最后|机构|地址| space3_1_value |   space3_2_value |协议

这是通过使用以下查询得出的:

id
first
last
institution
address
space1_1_value
space1_2_value
space2_1_value
space2_2_value
space3_1_value
space3_2_value
agreement

然而,我的任务是进一步打破这个问题,但我不确定这是否可以通过查询,或者实际上是否需要在后端/ PHP方面完成?

因此,请记住上述指令(这是一项要求):

因此,对于每个SPACE1.x组,都有一个以逗号分隔值的列。

为此,我们会说所有space1_2_value,space2_2_value& space3_3_value cols包含类似的内容:

SELECT first, last, space1_1_value as space_value FROM report
UNION ALL
SELECT first, last, space2_2_value as space_value FROM report WHERE space2_2_value <> ''
UNION ALL
SELECT first, last, space3_3_value as space_value FROM report WHERE space3_3_value <> ''
ORDER BY first

例如。

因此每个col可以有1到多个逗号分隔值。

在MySQL中是否有办法分解这些值,并为每个值返回一个镜像行?或者在事情的后端(PHP)方面需要做一些简单的事情?

我花了几分钟时间试着想一想我是怎么用PHP做的。

但是我在没有任何索引的情况下陷入了foreach()循环? (或者只是一个简单的for()循环WITH索引,但没有很多开销来检查每个$值是否为空(手动)。

2 个答案:

答案 0 :(得分:1)

这可以在 sql 中完成。一种方法是使用&#34;帮助表&#34;只有整数,你可以join你的数据反对多次获取你的行,然后只提取n个子元素。

试试这个:

-- helper table with a listof integers from 1 to 10
create table _int_1_10 (id int primary key);
insert into _int_1_10 (id) 
values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);

-- some example data 
create table test_strexplode (
   id int primary key, 
   space_value_1 varchar(200),
   space_value_2 varchar(200)
);

insert into test_strexplode (id, space_value_1, space_value_2)
values (1, 'row 1', 'March 3,March 5,March 6 March 1,March 2 Feb 27'),
       (2, 'row 2', 'March 3,,March 5'),
       (3, 'row 3', '');

select space_value_1, 
  _int_1_10.id,
  -- extracts the "_int_1_10.id"th element
  SUBSTRING_INDEX(SUBSTRING_INDEX(
       space_value_2,',',_int_1_10.id),',',-1) as subentry
from test_strexplode
join _int_1_10 
on _int_1_10.id <= 
   -- number of elements in your string (= number of "," + 1)
   char_length(space_value_2) - char_length(replace(space_value_2, ',', '')) + 1
order by test_strexplode.id, _int_1_10.id;

这会给你:

+---------------+----+-----------------+
| space_value_1 | id | subentry        |
+---------------+----+-----------------+
| row 1         | 1  | March 3         | 
| row 1         | 2  | March 5         |
| row 1         | 3  | March 6 March 1 |
| row 1         | 4  | March 2 Feb 27  |
| row 2         | 1  | March 3         |
| row 2         | 2  |                 |
| row 2         | 3  | March 5         |
| row 3         | 1  |                 |
+---------------+----+-----------------+

我使用了缺少某些,的示例数据,这就是为什么结果包含例如March 2 Feb 27。另请注意,某些子条目为空(因为我的示例数据包含空条目);你可能想要也可能不想过滤掉它们。你的整数表显然必须包含至少达到你希望在任何行中具有的最大元素数的数字(如果它包含0或负数,请在{{1 }} - 。子句)

substring_index(str,delim,count)on出现分隔符str之前返回字符串count的子字符串。对于正数,delim的完整语句将返回subentry - 元素,或者,如果字符串具有较少元素,则返回最后一个元素。

_int_1_10.id - 子句因此计算元素的数量(通过计算on的数量)以防止多次获取最后一个元素。如果您的字符串不包含任何空元素(例如我的示例数据中的,),则您不需要该部分,但可以添加一个空元素来标记列表的末尾。

您可以将此代码应用于整个结果集,例如使用

,,

它会起作用,但可能会很慢。它不能在... from (select ... space1_1_value as space_value_1, space1_2_value as space_value_2 ... union all ... union all ... ) as test_strexplode join _int_1_10 ... - 列上使用索引,并且必须进行大量的连接和字符串评估。除了规范化数据之外,你无法做很多事情。

如果在 sql 中执行此操作很有用,则可能取决于您对数据执行的操作。如果您只是要在网页上的html表中显示它,那么在 php 中循环遍历数组可能会更容易,更快捷。要对结果集进行排序,过滤或space*_2_value,它可能更容易在 sql 中实现(并且可能更快),即使您在框架中使用它也是如此。如果你要更新这些值,那么在 php 中会更容易,因为它很可能会在 sql 中混乱(在这个结果集上)

答案 1 :(得分:0)

代表OP发表答案

我为此推出了自己的PHP解决方案(但感谢@Solarflare获取SQL解决方案)。

PHP :(显然使用UNION ALL QUERY ......等)

$getRequests_stmt = $conn->prepare($getRequests_sql);
$getRequests_stmt->execute();
$getRequests_stmt->setFetchMode(PDO::FETCH_ASSOC);
$results = $getRequests_stmt->fetch(PDO::FETCH_ASSOC);
$colcount = $getRequests_stmt->columnCount();
$rowcount = $getRequests_stmt->rowCount();
$date = new DateTime();
$currdate = "Results as of: ".$date->format('m-d-Y H:i:s');
$namedate = $date->format('m-d-Y-H_i_s');    
//Get Headers
for ($i = 0; $i < $colcount; $i++) {
                $col = $getRequests_stmt->getColumnMeta($i);
    $colname = $col['name'];
    $header .= $colname . "\t";
}

//Get Row Data
while ($results = $getRequests_stmt->fetch()){                                
                $line = '';
    foreach($results as $key => $value) {
        if ((!isset($value)) || ($value == '')) {
            $value = "\t";
        } else {
            $value = str_replace('"', '""', $value);
            $value = '"' . $value . '"' . "\t";
        }
        $line .= $value;
    }
    $data .= trim($line) . "\n";        
}

//Data check
$data = str_replace("\r", '', $data);
if ($data == '') { 
    $data = "\n(0) space requests found\n";
}

//Export spreadsheet...