Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/237.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php MySQL表联接、嵌套select语句或创建视图?_Php_Mysql_Select - Fatal编程技术网

Php MySQL表联接、嵌套select语句或创建视图?

Php MySQL表联接、嵌套select语句或创建视图?,php,mysql,select,Php,Mysql,Select,免责声明:我先在另一个网站上发布了这个 我有一个大约200列宽的表(res_table)。其中一列名为“feature_lk”,它由一串以“|”分隔的数字组成。这些数字代表位于另一个名为“features”的表中的要素类别 多亏了这个帖子:我知道了如何解析这些特性 现在我的问题是如何查找它们?我觉得我要么需要连接我的两个表,但我不确定如何连接,要么需要为我解析的每个功能执行另一个select查询。。这就是我要做的(删除连接字符串以便于发布) 我的问题是:有没有更好的方法?主resu表中大约有10

免责声明:我先在另一个网站上发布了这个

我有一个大约200列宽的表(res_table)。其中一列名为“feature_lk”,它由一串以“|”分隔的数字组成。这些数字代表位于另一个名为“features”的表中的要素类别

多亏了这个帖子:我知道了如何解析这些特性

现在我的问题是如何查找它们?我觉得我要么需要连接我的两个表,但我不确定如何连接,要么需要为我解析的每个功能执行另一个select查询。。这就是我要做的(删除连接字符串以便于发布)

我的问题是:有没有更好的方法?主resu表中大约有10k行,只有几百次点击,您可以看到执行的select语句的数量在任何时候都会增长


我肯定这是PHP+MySQL 101的东西,但我只是个初学者,有什么想法吗?提前感谢。

您在这里感受到了糟糕的数据库建模带来的痛苦。如果您对数据库模式有任何控制权,那么应该对其进行修复,以使其正常化。每当您在数据库中看到一个管道(或逗号、制表符或其他什么)被删除的列表时,您都应该非常怀疑它

您的表和类别之间应该有一个连接表,通常命名为RES_categories,其中包含RES的ID和categories的ID。这是在关系数据库中建模多对多关系的标准方法


如果您无法控制模式,那么最好的办法就是在代码中解析模式,然后执行一个或多个单独的查询来获取类别信息。您至少可以在where子句中指定多个类别ID,以稍微减轻痛苦。

根据我在您的问题中的理解,您需要一个中间表。例如,您有表tbl_user和tbl_features,其中用户可以订阅多个功能,每个功能可以由多个用户订阅


使用额外的表tbl_userfeatures{userFeatureID,userID,featureID},您的数据库将更易于管理,该表链接其他两个表并允许您添加不同的组合

当您在一列中存储多条信息时,您的表不会规范化。查找
功能\u lk
必然会非常缓慢和困难<代码>功能_lk应成为其自己的表格:

表格特征:

  • res_表\u id FK到res_表
  • 要素标识FK到要素表
  • 主键(资源表id、功能id)
那么您的查询是:

SELECT f.* from features f 
  JOIN feature_lk lk ON (f.id=lk.feature_id) 
  JOIN res_table r ON (lk.res_table_id=r.id);
只有一个查询。没有循环。没有解析出这些特性

埃塔

用任意字符拆分任意长度字符串的存储过程

DELIMITER $$

DROP PROCEDURE IF EXISTS `dorepeat` $$
CREATE PROCEDURE `dorepeat`(in ToBeSplit LONGTEXT , in Splitter CHAR)
Begin

DECLARE TotalLength INT;
DECLARE SplitterPosition INT;
DECLARE SubstringLength INT;
DECLARE SubstringStart INT;

DROP Table if exists Split_Values;
CREATE temporary TABLE Split_Values (split varchar(255));

SET TotalLength = LENGTH(ToBeSplit);
SET SplitterPosition = LOCATE(Splitter, ToBeSplit);
SET SubstringStart = 1;

ss: WHILE SplitterPosition < TotalLength DO
        IF SplitterPosition!=0 THEN 
                SET SubstringLength = SplitterPosition - SubstringStart;
                Insert into Split_Values VALUES (SUBSTRING(ToBeSplit,SubstringStart,SubstringLength));
                SET SubstringStart = SplitterPosition+1;
                SET SplitterPosition = LOCATE(Splitter, ToBeSplit, SplitterPosition+1);
        ELSE
                Insert into Split_Values VALUES (SUBSTRING(ToBeSplit,SubstringStart));
                SET SplitterPosition=TotalLength;
        END IF;
END WHILE ss;
End $$

DELIMITER ;

一个简单的优化步骤是在一个步骤中获取特性,而不是在其上循环。大概是这样的:

13: None
62: Water Softener - Rented
71: Full
168: Barn
222: Storage Shed
226: Walkout
309: Detached
347: 2 Story
384: Attic Storage
439: Laundry Hook Up
466: Rural
476: Trees
512: School Bus
562: Mud Room
563: Pantry
2273: Septic Tank
643: Private Well
$result = mysql_query('SELECT * FROM res_table');
while ($row = mysql_fetch_array($result)) {
    $features = str_replace('|', ',', $features);
    $result2 = mysql_query("SELECT * FROM features WHERE feature_id IN $features");
    while ($row2 = mysql_fetch_array($result2) {
        printf('%d: %s', $row2['feature_id'], $row2['feature_description']);
    }
}
这是针对res_表中的每一行的一个查询,而不是针对每个特性的一个查询


但在你这么做之前,先听听其他的回答。如果您能够将数据库模式更改为更合理的模式,请这样做

现在我既控制着模式,又不控制模式。它是一个通过文本文件共享数据的MLS。我将这些文本文件(以选项卡分隔)导入mysql数据库表。我想我可以在导入时解析出这些特性并创建一个新表?这可能吗?爱德华:是的,可能。您需要“加载数据填充”选项卡分隔的文件。然后,您可以使用一个函数将feature_lk字段解析到另一个表中,就像我在答案中添加的函数一样。
DELIMITER $$

DROP PROCEDURE IF EXISTS `multido` $$
CREATE PROCEDURE `multido`()
Begin
DECLARE done INT default 0;
DECLARE rt_id INT (10);
DECLARE features LONGTEXT;
DECLARE mycur cursor for select distinct res_table_id, feature_lk from res_table WHERE feature_lk!='';
DECLARE continue handler for sqlstate '02000' set done=1;
drop table if exists tmpfeatures;
create temporary table tmpfeatures( res_table_id int(10),  feature varchar(255));
open mycur;
repeat
  fetch mycur into rt_id,features;
  call dorepeat(features,'|');
  insert into tmpfeatures select rt_id, trim(split) from Split_Values;
until done end repeat;
close mycur;

End $$

DELIMITER ;
$result = mysql_query('SELECT * FROM res_table');
while ($row = mysql_fetch_array($result)) {
    $features = str_replace('|', ',', $features);
    $result2 = mysql_query("SELECT * FROM features WHERE feature_id IN $features");
    while ($row2 = mysql_fetch_array($result2) {
        printf('%d: %s', $row2['feature_id'], $row2['feature_description']);
    }
}