【问题标题】:How can I filter one column by two AND conditions?如何通过两个 AND 条件过滤一列?
【发布时间】:2019-12-24 17:36:17
【问题描述】:

问题已解决。但是,如果您有“更好”或其他方式来做到这一点,请随时添加评论!感谢大家阅读! :)

我正在尝试进行动态查询。除了一件事,一切都运行良好。我已经用 Google 搜索了好几天,但我不知道如何进行以下工作;

SELECT project.name, project.description, track.name, track.description
   , SDG.position, SDG.title, SDG.description
   , sprint_numbers.number, sprint_options.option
   , resources.name, resources.description
   , URLs.URL 
FROM project INNER JOIN track ON project.track_id = track.id 
INNER JOIN project_SDG ON project.id = project_SDG.project_id 
INNER JOIN SDG ON project_SDG.SDG_id = SDG.id
INNER JOIN sprint ON sprint.project_id = project.id 
INNER JOIN sprint_numbers ON sprint_numbers.id = sprint.sprint_number_id 
INNER JOIN sprint_options ON sprint_options.id = sprint.sprint_option_id 
INNER JOIN resources ON project.id = resources.project_id 
INNER JOIN URLs ON URLs.id = resources.id 
WHERE 1=1 
   AND MATCH (project.name) AGAINST (:name_project) 
   AND MATCH (project.description) AGAINST (:description_project) 
   AND SDG.id = :SDG_1 
   AND SDG.id = :SDG_2

查询执行但不返回任何内容。问题是 SDG.id 不能同时适用于 :SDG_1 和 :SDG_2。

使用 OR 运算符有效,但这并不能以我想要的方式返回。它必须“充当” AND 运算符。 (:SDG_1 & :SDG_2 是绑定到 SQL 语句参数的 PHP 变量的名称。)

查询应该过滤这两个值。给 :SDG_1 和 :SDG_2 的值必须都存在于 project_SDG 表的 SDG.id 列中。如果 :SDG_1 的值存在,但 :SDG_2 不存在,则查询不应返回任何内容。

我在 StackOverflow 上找到了这个,但它对我不起作用:SELECTING with multiple WHERE conditions on same column

希望有人能帮帮我。

编辑:最小的可重现示例

查询:

SELECT * FROM project
INNER JOIN project_SDG ON project.id = project_SDG.project_id 
INNER JOIN SDG ON project_SDG.SDG_id = SDG.id
WHERE SDG.id = 1 AND SDG.id = 7 AND SDG.id = 14 AND SDG.id = 17

项目表

+------------------+---------------------------+------------+
|     id  name     |        description        |  track_id  |
+------------------+---------------------------+------------+
| 1   project name | This is a description   2 |            |
+------------------+---------------------------+------------+

可持续发展目标表

+-----+-----------+-------------+---------------------------------------------+
| id  | position  |   title     |                 description                 |
+-----+-----------+-------------+---------------------------------------------+
|   1 |         1 | SDG 1 to 17 | There're multiple SDGs ranging from 1 to 17 |
|  17 |        17 | SDG 1 to 17 | There're multiple SDGs ranging from 1 to 17 |
+-----+-----------+-------------+---------------------------------------------+

project.SDG(桥接表)

+------------+--------+
| project.id | SDG.id |
+------------+--------+
|          1 |      1 |
|          1 |      2 |
|          1 |      3 |
+------------+--------+

【问题讨论】:

  • stackoverflow.com/help/minimal-reproducible-example - 请发布您的表结构和记录。
  • 正确。表行中的单个字段不能有多个值。通常这类问题需要类似“tableA rows that have tableB rows with each value provided”之类的问题,但这会导致在这种情况下应该为 SELECT 子句中的值使用哪个“B 行”的问题。跨度>

标签: php mysql sql where-clause


【解决方案1】:

您希望每个project.id 的值:SDG_1:SDG_2 都存在于SDG.id,所以在WHERE 子句中使用它:

WHERE 1=1 
    AND MATCH (project.name) AGAINST (:name_project) 
    AND MATCH (project.description) AGAINST (:description_project) 
    AND project.id IN (
        SELECT project_id
        FROM project_SDG
        WHERE SDG_id IN (:SDG_1, :SDG_2)
        GROUP BY project_id
        HAVING COUNT(DISTINCT SDG_id) = 2
    ) 

【讨论】:

  • 是的,你是对的。 “两个值或更多”。这取决于用户选择什么。在我的示例中,我使用了 :SDG_1 和 SDG_2,但它的范围从 1 到 17。我尝试了这个查询,但它没有返回任何内容。 (我在发布之前尝试了完全相同的事情)我将 PHP 变量 (:SDG_1 & :SDG_2) 替换为 (1, 2) 这些值存在于列中,但我没有得到结果。
  • IN 之后的子查询返回所有同时具有 :SDG_1 和 :SDG_2 值的 project.id。我试图在没有任何连接的情况下对其进行简化,因此我只使用了包含 project_id 列和 SDG_id 列的表 project_SDG。
  • 我很抱歉。你有我的感激之情!有用!但是你确实让我的查询变得动态化了。我希望会有一个更“优雅”的解决方案。但是,如果它有效,那么它就有效!再次感谢!我可以从这里解决剩下的问题。
【解决方案2】:

您能否为您的查询提供minimal reproducible example
一般来说,一个字段不能同时等于两个不同的值。因此,您要么混淆了逻辑运算符,要么需要两个不同的字段。

我可以假设在您的情况下可能有多个具有不同值的相关记录。在这种情况下,您需要使用不同的别名将同一个表连接两次。假设为SDG1SDG2。之后就可以比较了

... `SDG1`.id = :SDG_1 AND `SDG2`.id = :SDG_2

更新:

获胜的诀窍是分组。您可以枚举所有必需的 SDG ID 并计算其中有多少在组中。以两个 ID 为例:

SELECT project.id
FROM project
JOIN project_SDG ON project_SDG.project_id = project.id
JOIN SDG ON SDG.id = project_SDG.SDG_id
WHERE SDG.id IN(1,2)
GROUP BY project.id
HAVING COUNT(*) = 2

在这里查看我的沙盒:https://www.db-fiddle.com/f/pixe3Zcs75Mq2PyCYPk913/0

如果您需要所有项目的字段,则必须将其放入子查询中

... WHERE id IN ( subquery here )

子查询示例:https://www.db-fiddle.com/f/pixe3Zcs75Mq2PyCYPk913/1

【讨论】:

  • 我确实用更多信息更新了我的问题。多次连接表实际上并不可行。我无法为 17 个可持续发展目标创建 17 个单独的表格。 (抱歉造成混乱,总共有2个以上,17个)
  • @May 谢谢你的更新。我会相应地更新我的答案。
  • 我明白了,谢谢你的回复。你的小提琴似乎工作正常!但是,当我尝试在“WHERE 子句”之后添加所有内容时,我收到一条错误消息 #1055。我确实认为您的解决方案比另一个更好,但我似乎无法弄清楚为什么它不适用于我自己的查询。我必须先对 #1055 和非聚合列进行研究,然后才能将您的列实现到我自己的查询中。谢谢你的帮助!我真的很感谢你所经历的所有麻烦! :)
【解决方案3】:

我已经在这里回答了,但是我有另一种方法。

1。查找与某个项目相关联的一堆 ID

要查找项目 ID,我们可以测试 没有任何连接的孤独数据透视表

  SELECT project_id FROM project_SDG
  WHERE SDG_id IN(1,2,6)
  GROUP BY project_id HAVING COUNT(*) = 3

它为我们提供了项目 ID 列表

2。访问所有项目字段并添加额外条件

SELECT project.*
FROM project
JOIN (
  SELECT project_id FROM project_SDG
  WHERE SDG_id IN(1,2,6)
  GROUP BY project_id HAVING COUNT(*) = 3
) AS ids ON ids.project_id = project.id
WHERE
  MATCH(project.name) AGAINST ('project') AND
  MATCH(project.description) AGAINST ('sit')

你可以在这里玩:https://www.db-fiddle.com/f/pixe3Zcs75Mq2PyCYPk913/3

3。在 PHP 端准备查询

我会使用known technique来准备SQL语句。

$ids = [1, 2, 6]; // it can come from request parameters
$text1 = 'project';
$text2 = 'sit';
// build ?,?,?,... pattern
$qmarks = implode(',', array_fill(0, count($ids), '?'));
// Use SQL query above
$sth = $dbh->prepare("
SELECT project.*
FROM project
JOIN (
  SELECT project_id FROM project_SDG
  WHERE SDG_id IN({$qmarks})
  GROUP BY project_id HAVING COUNT(*) = ?
) AS ids ON ids.project_id = project.id
WHERE
  MATCH(project.name) AGAINST (?) AND
  MATCH(project.description) AGAINST (?)
");
$sth->execute(array_merge($ids, [count($ids), $text1, $text2]));
$records = $sth->fetchAll();

【讨论】:

    猜你喜欢
    • 2019-03-31
    • 1970-01-01
    • 2018-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-23
    • 1970-01-01
    相关资源
    最近更新 更多