用一次查询获取剩余的结果

3

之前的问题:Select2问题

现在的问题:一个与SQL强相关的问题。(我不想浪费悬赏,因为我没有得到答案,我的悬赏仍然开放!)

基本上,我有两个查询。一个是通用的,另一个是基于搜索的。

第一个查询:获取所有内容(没有问题)

SELECT store_info.storeID, store_info.name, store_info.address, store_info.phone, GROUP_CONCAT(brands.name) AS brands
FROM store_info, brands, stores, store_brands
WHERE stores.city = $cityID
AND store_brands.store =  stores.ID
AND brands.id = store_brands.brand
AND stores.ID = store_info.storeID
GROUP BY store_info.storeID
ORDER BY store_info.name

这个查询完全符合我的要求,它给出的商店品牌格式为brand1,brand2,brand3,brand4,brand5等等。现在,我还有一个搜索功能,可以根据品牌搜索商店。基本上是相同的查询,只需要进行一点小改动(这里有问题)
SELECT store_info.storeID, store_info.name, store_info.address, store_info.phone, GROUP_CONCAT(brands.name) AS brands
FROM store_info, brands, stores, store_brands
WHERE stores.city = $cityID 
AND store_brands.store =  stores.ID
AND brands.ID = store_brands.brand
AND stores.ID = store_info.storeID
AND brands.ID IN (" . implode(",", $brandIDs) . ")
GROUP BY store_info.storeID
ORDER BY store_info.name

这个最后一个查询的问题是,我仍然希望它返回所有品牌。我只想稍后处理搜索的品牌。在我看来,我应该能够以多种方式做到这一点:
1) 在查询中返回所有品牌,并在 PHP 中遍历时操作这些品牌(我已经存储了搜索词,但不知道如何在不获取所有商店(这不是我想要的东西)的情况下完成此操作)
2) 返回一个字段与所搜索匹配的品牌,另一个字段则包含剩余品牌。(理想的选择,但我不知道如何实现。将整个查询放入连接中并进行微调似乎效率低下)
3) (效率低下且我不喜欢它)从查询中获取找到的商店,运行新的查询寻找与找到的商店相关的品牌,然后使用 PHP 将结果合并。但是,这会添加一个额外的查询,而效率是优先考虑的。
如果有人搜索两个品牌,并且存在与两者匹配的商店,则只会显示其中1个品牌。 (我猜测是第一个命中的)
非常感谢您对此最后一个查询的帮助!
提前致谢!
编辑:对搜索功能的更多深入了解 搜索功能搜索与搜索的品牌相关的商店。它应该显示连接到这些品牌的商店,但不仅限于返回只搜索过的品牌。

搜索栏是什么?我在你的示例中没有看到它。你所说的“轻拍”是什么意思? - roydukkey
移动端的轻触操作和桌面端的点击操作相同。搜索栏是...嗯...你输入搜索词的那个栏。它是由select2创建的文本输入框。一旦你在里面输入,它就会给你一个下拉菜单显示结果。然后你可以选择(多个)结果作为“标签”(非常类似于这里的标签,只是你可以让它保持打开状态)。但是,在选择完选项后重新选择搜索栏时,select2将重新初始化并清空搜索栏。 - NoobishPro
使标签属性显示为none的目的是什么? - Mohammedshafeek C S
如果你能够缩小问题陈述的范围,不包含额外的代码(例如ajax调用等),将会很有帮助。 - Selvakumar Arumugam
Mohammed,这是因为标签会推出搜索栏,否则下拉菜单已经显示了所选内容。标签是多余的。-@SelvakumarArumugam 完成。 - NoobishPro
3个回答

1
你可以在store_brands表中再次加入一次(在以下代码中使用AS restraint),并将限制条件放在其中一个上面:
SELECT store_info.storeID, store_info.name, store_info.address, store_info.phone, GROUP_CONCAT(DISTINCT(brands.name)) AS brands
FROM store_info, brands, stores, store_brands, store_brands AS restraint
WHERE stores.city = $cityID 
AND store_brands.store =  stores.ID
AND brands.ID = store_brands.brand
AND stores.ID = store_info.storeID
AND restraint.ID IN (" . implode(",", $brandIDs) . ")
GROUP BY store_info.storeID
ORDER BY store_info.name

通过两次加入表格,它将被用于 (1) 该商店中所有可用的品牌和 (2) 限制所选商店为具有一个或多个指定品牌的商店。

你是否将 store_brands AS restraint 添加到你的 FROM 表列表中了?这对我来说很有效。 - Paul
是的,这是因为它应该是.brand而不是.ID,我的错。无论如何,它现在不起作用。它返回所有商店,因此与仅获取所有内容的查询没有区别。我得到了81个结果 - 我应该只有4个。 - NoobishPro
你能创建一个SQLFiddle吗?我重新创建了一个更简单的问题(只涉及商店和品牌),并且它可以工作。根据你的数据库模式,仅使用JOIN而不是INNER JOIN可能不明智。 - Paul
我想告诉你,我已经完全重建了所有的查询,就像这样(多亏了你们,现在我对此有了更好的理解!),我确实使用同一张表的多个连接来获取不同关系的特定数据。--只是想感谢你们让我认识到这一点,并给你一个赞 :) - NoobishPro

1

GROUP_CONCAT 忽略 NULL,所以你可以像这样创建一个你的匹配项的 GROUP_CONCAT

SELECT
store_info.storeID,
store_info.name,
store_info.address,
store_info.phone,
GROUP_CONCAT(brands.name) AS brands,
GROUP_CONCAT(
  CASE WHEN brands.ID IN (" . implode(",", $brandIDs) . ")
    THEN brands.name
    ELSE NULL
  END
) AS available_brands
FROM
stores
INNER JOIN store_info ON (stores.ID = store_info.storeID)
INNER JOIN store_brands ON (stores.ID = store_brands.store)
INNER JOIN brands ON (store_brands.brand = brands.id)
WHERE stores.city = $cityID
GROUP BY store_info.storeID
ORDER BY store_info.name

Fiddle: http://sqlfiddle.com/#!9/83e576/1


我不完全确定那是什么意思,但还是谢谢你=) 无论如何,这个查询确实有效!它向我展示了匹配项和品牌列表。完美!- 但是,它显示所有未匹配的内容为“NULL”。有没有办法在第一次检索时不检索这些未匹配的商店? - NoobishPro
如果我添加 AND store_brands.brand IN(18),它将再次仅在总品牌列表中返回1个品牌。我的SQL知识真的不是我最自豪的领域...我根本没有内部连接的经验。(我曾经使用过umbraco,所以我从未涉足数据库) - NoobishPro
当你说一个非匹配的存储时,你能给我举个例子吗? - trex005
一个非匹配的商店,意味着 "available_brands" 是 "null"。但是这个问题已经通过 HAVING LENGTH(available_brands) > 0 得到解决。我只希望它不会破坏效率 ;) - NoobishPro
1
如果我们有机会见面,我一定会请你喝啤酒。非常感谢! - NoobishPro
显示剩余6条评论

0

SELECT 子句中使用 CASE 语句,根据匹配条件返回 true 或 false,即如果 brands.ID$brandIDs 列表中,则返回 true。

SELECT
  store_info.storeID,
  store_info.name,
  store_info.address,
  store_info.phone,
  GROUP_CONCAT(brands.name) AS brands,
  (
    CASE 
    WHEN brands.ID IN (" . implode(",", $brandIDs) . ") THEN 1
    ELSE 0 --no match
    END 
  ) AS matches
FROM store_info, brands, stores, store_brands
WHERE stores.city = $cityID 
AND store_brands.store =  stores.ID
AND brands.ID = store_brands.brand
AND stores.ID = store_info.storeID
GROUP BY store_info.storeID
ORDER BY store_info.name

这个想法是,如果brands.ID$brandIDs中的一个ID,则在matches列中返回1。否则,将返回0


通过匹配条件,您指的是品牌的ID吗?它只是简单的ID,如25、36等。 我现在要尝试一下。 - NoobishPro
它与任何内容都不匹配,所以它无法工作。我并不完全理解这个查询,所以我不知道原因。(我没有收到任何错误消息,并且我知道我正在使用的ID应该匹配) - NoobishPro
它应该返回所有结果,就像第一个查询一样,但是还会有一个额外的列,如果brands.ID$brandIDs中,则返回1 - br3nt
1
它是按商店分组的,会有多个品牌。这个查询不起作用。 - trex005

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接