ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

php-通过MySQL中的特定关键字对结果进行分组?

2019-12-02 04:25:45  阅读:305  来源: 互联网

标签:tagging sql-like mysql php group-by


我的网页上有多个带有我正在搜索的关键字的标签,有时它没有使用该关键字进行标签,因此当它具有该标签时,它将在下面返回类似这样的结果,

查询,

SELECT*
FROM root_pages AS p

LEFT JOIN root_mm_pages_tags AS mm
ON mm.page_id = p.page_id

LEFT JOIN root_tags AS t
ON t.tag_id =  mm.tag_id
AND t.tag_name LIKE '%story%'

WHERE p.page_title LIKE '%article title 8%'
AND p.page_hide != '1'

ORDER BY (t.tag_name+0) ASC

结果,

page_id     page_url            tag_name    
17          article title 8     NULL
17          article title 8     NULL
17          article title 8     sys-rsv-story-1

所以我必须使用GROUP BY来解决这个问题,

SELECT*
FROM root_pages AS p

LEFT JOIN root_mm_pages_tags AS mm
ON mm.page_id = p.page_id

LEFT JOIN root_tags AS t
ON t.tag_id =  mm.tag_id
AND t.tag_name LIKE '%story%'

WHERE p.page_title LIKE '%article title 8%'
AND p.page_hide != '1'

GROUP BY p.page_id
ORDER BY (t.tag_name+0) ASC

它返回这样的内容,

page_id     page_url            tag_name    
17          article title 8     NULL

但是,在此结果之后,我有了我要搜索的关键字,

page_id     page_url            tag_name    
17          article title 8     sys-rsv-story-1

那么,是否可以通过关键字将结果分组?还是其他更好的查询来存档?

此外,如果该关键字不存在,则不应返回结果,但仍会返回结果,

page_id     page_url            tag_name    
    17          article title 8     NULL
    17          article title 8     NULL

编辑:

我的新解决方案

 SELECT*
FROM root_pages AS p

INNER JOIN root_mm_pages_tags AS mm
ON mm.page_id = p.page_id

INNER JOIN root_tags AS t
ON t.tag_id =  mm.tag_id

WHERE p.page_title LIKE '%{group1}%'
AND t.tag_name LIKE '%story%'
AND p.page_hide != '1'

AND EXISTS (
    SELECT page_url
    FROM root_pages AS p

    LEFT JOIN root_mm_pages_tags AS mm
    ON mm.page_id = p.page_id

    LEFT JOIN root_tags AS t
    ON t.tag_id =  mm.tag_id

    WHERE page_url = 'article title 1d'
    AND t.tag_name LIKE '%story%'
    AND p.page_hide != '1'
)

ORDER BY (t.tag_name+0) ASC

解决方法:

哎uch

我认为您的SQl查询非常奇怪.

需要注意的几件事:

>对于SQL引擎,使用栏LIKE’%foo%’非常困难,他必须顺序扫描所有行并在列栏中搜索子字符串’foo’.索引用法不可用.因此,如果可以,请避免使用它.如果可以的话,至少使用bar LIKE’foo%'(如果有开始就可以使用索引).而且,如果您的页面标题匹配“ article title 80”,您确定不只是需要p.page_title =“ article title 8”吗?
>为什么您按指令将顺序设为0?您真的要防止使用索引吗?
> p.page_hide!=’1′,p.page_hide不是tinyint吗?这是一个字符串吗?为什么使用UTF8编码的字符存储0或1?

但这不是问题.

您的问题之一是在SQL中使用GROUP BY p.page_id分组实际上是错误的,但是MySQL隐藏了这一事实.按指令进行分组应至少包含在SELECT部分​​中不是aggegate的每个元素(聚合是count或sum或avg等).在这里,您按id分组并获得随机的东西,MySQL认为您知道自己在做什么,并且确保id相同时select中的所有其他字段都相同(不是这种情况,tag_name不同).

而且,如果您有多个与关键字匹配的标签(此处为“故事”),您是否不想将该页面多次列出?所有标签?

所以.

您想要选择一个有标签的页面.我会说使用EXISTS关键字并使事情变得更简单.

可能是这样的:

SELECT * 
 FROM root_pages AS p
WHERE p.page_title = 'article title 8'
 AND p.page_hide != 1
 -- exists will return true as soon as the engine find one matching row
 AND EXISTS (
  SELECT mm.page_id
  FROM root_mm_pages_tags AS mm
    LEFT JOIN root_tags AS t
      ON t.tag_id =  mm.tag_id
  -- here we make a correlation between the subquery and the main query
  WHERE mm.page_id = p.page_id
  AND t.tag_name LIKE '%story%'
)

但是通过此查询,您只能获取页面名称,而不是标签结果.而且,如果要列出页面的所有匹配标签,则需要另一个查询,该查询与您拥有的查询非常接近:

SELECT p.page_id, p.page_name, t.tag_name
 FROM root_pages AS p
   INNER JOIN root_mm_pages_tags AS mm
       ON mm.page_id = p.page_id
     INNER JOIN root_tags AS t
         ON (t.tag_id =  mm.tag_id 
         AND t.tag_name LIKE '%story%')
WHERE p.page_title = 'article title 8'
 AND p.page_hide != 1

通过第一个INNER JOIN,我只保留带有标签的页面.在第二个INNER JOIN中,我只保留root_mm_pages中具有root_tags中匹配标签的行.我认为您的NULL来自此表中链接到其他不匹配标签的行(因此root_tags表结果中有NULL字段供您查询).因此,如果您只想要匹配结果,请不要使用LEFT JOIN.

如果每个表只需要一个结果,则需要一个GROUP BY p.page_id,p.page_name,并且需要在其余字段t.tag_name上添加聚合函数.您可以使用GROUP_CONTACT(t.tag_name ORDER BY t.tag_name ASC SEPARATOR“,”)获得该表所有匹配标签的列表.

编辑

因此,实际上您似乎想要标题匹配的页面或关键字匹配的页面.在这种情况下,您应该使用LEFT JOIN,并且您将拥有NULL值.如果结果中不需要标记,则EXISTS关键字仍然是您最好的朋友,只需将AND EXISTS替换为OR EXISTS.这是最快的解决方案.

如果结果中需要匹配的标签,或者当它们不是标签时需要NULL,则有2个解决方案. UNION查询混合了来自标题的简单查询和具有内部联接的标签查询的结果,或者通过GROUP_CONCAT进行了很好的分组.如果不使用GROUP_CONCAT(如@Dmitry Teplyakov回答),则可能会获得页面标题不匹配的结果,只有关键字,但tag_name字段将显示NULL,这是应用GROUP BY之前列出的第一个tag_row.在查询中是一个NULL字段-该页面作为3个关键字,匹配关键字不是查询中的第一个-.

SELECT 
 p.page_id,
 p.page_name,
 GROUP_CONCAT(t.tag_name ORDER BY t.tag_name ASC SEPARATOR ",")
FROM root_pages AS p
   LEFT JOIN root_mm_pages_tags AS mm
       ON mm.page_id = p.page_id
     LEFT JOIN root_tags AS t
         ON t.tag_id =  mm.tag_id 
WHERE p.page_hide != 1
 AND (p.page_title = 'article title 8'
  OR t.tag_name LIKE '%story%')
GROUP BY p.page_id, p.page_name;

但是在这里,我们通过tag_name取消了您的订单.按tag_name排序意味着,如果同一页面多次匹配关键字,则您希望该页面显示在多行中.或者,如果名称匹配并且关键字也匹配…或者可能不匹配.因此,实际上UNION查询解决方案可能更好.但是关键是您应该在tag_name字段中解释您想要的内容:-)

标签:tagging,sql-like,mysql,php,group-by
来源: https://codeday.me/bug/20191202/2085919.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有