Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/67.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
Mysql 获取SQL查询中与列表匹配的所有行_Mysql_Sql_Where In - Fatal编程技术网

Mysql 获取SQL查询中与列表匹配的所有行

Mysql 获取SQL查询中与列表匹配的所有行,mysql,sql,where-in,Mysql,Sql,Where In,我使用以下SQL查询选择与列表(9,10)中的任何值匹配的任何行: 我试着找出如何做相反的事情,我也需要这样做,即选择匹配所有值的行 我读到过这样一种说法: SELECT r.id, r.title FROM resource r WHERE id IN ( SELECT resource_id FROM category_resource WHERE

我使用以下SQL查询选择与列表(9,10)中的任何值匹配的任何行:

我试着找出如何做相反的事情,我也需要这样做,即选择匹配所有值的行

我读到过这样一种说法:

SELECT
    r.id, r.title
FROM
    resource r
WHERE
    id IN (
        SELECT
            resource_id
        FROM
            category_resource
        WHERE
            category_id IN (9, 10)
        GROUP BY
            resource_id
        HAVING
            COUNT(DISTINCT category_id) = 2
    );
这是我根据自己的需要调整答案的尝试:

但这并不像第一句话那样让我在结果中得到那么多的信息。那么,我怎样才能做一些更等效的事情呢?我试着把它放在一起,但我对SQL太陌生了,无法正确地理解它,我只是得到了错误

长期更新:

戈登·林诺夫指出,这是一个奇怪的要求。我知道,我也觉得很奇怪,对于同一个资源,有一个返回多行的查询。但我不知道如何以其他方式实现这一点,也许我完全走错了方向,因为我突然意识到原始请求(获取所有资源行,其中类别与列表中任何类别匹配的请求)也不能满足我的要求

以下是我的总体要求:

首先,我认为db这一部分的模型可能会有所帮助

(顺便说一句,类别本身也有关系,因为它被存储为一个层次结构,使用邻接模型,其中每个类别存储其父id,如果有人想知道该箭头…)

1:查找类别与列表中任何值匹配的所有资源。但是(这是不够的)对于这些资源中的每一个,我需要知道资源以及它拥有的所有类别

让我用一个简单的例子来解释这一点:

正如你所看到的,这是一种多对多的关系。一个资源(比如说标题为“18世纪新英格兰木工入门”)可以与许多类别相关联(例如category.name=“subject”value=“Carpentry”、category.name=“subject”value=“Wood”、category.name=“subject”value=“newengland”、category.name=“subject”value=“History”)。请注意,本例已简化,但您看到了基本思想

现在,如果用户搜索的资源与“木工”和“绘画”中的任何一个类别相匹配,那么“18世纪新英格兰木工简介”应该会出现在搜索结果中,因为其中一个类别匹配。但是,问题是,戈登为什么觉得我的请求很奇怪:在搜索结果中,我想对于用户,我想列出标题“18世纪新英格兰木工简介”以及一个列,显示标题所属的所有类别,即使用户没有搜索这些类别-以便更好地概述此资源的完整主题

那么我该怎么做呢?我唯一能想到的就是我问题中的第一句话,但正如我所说的,它并没有给我一个资源可能拥有的所有类别,只有那些实际搜索到的类别

当然,我可以先对结果进行查询,每个结果只得到一行。然后再进行第二次查询,查找结果中每个资源的所有类别。但是如果第一次查询得到1000个结果(这将是常见的),然后要获得所有这些的类别,我必须进行1000次查询才能获得每个类别的类别…听起来这会给我带来性能问题

我是否有错误的想法?是否有其他方法来完成我想做的事情?例如,给我查询选择的资源,以及该资源的所有关联类别


2:好的,在经过长时间的解释之后,第二个要求更容易解释:关于为所选资源返回所有类别,同样是这样,但是这次查询中的选择应该只获取与所有提供的值匹配的资源oesn’意味着我已经拥有了所有类别,因为结果中的每个资源实际上可能有更多(和其他)类别,并且我在呈现第一个(任何)要求中提到的结果时也需要这些类别。

您可以将结果重新加入:

SELECT u.name as "Created By", c.name as 'Category', c.value, cr.category_id
FROM resource r join
     user u
     on r.created_by = u.id join
     (SELECT resource_id
      FROM category_resource
      WHERE category_id IN (9, 10)
      GROUP BY resource_id
      HAVING COUNT(DISTINCT category_id) = 2
     ) crr
     on r.id = crr.resource_id join
     category_resource cr
     on cr.resource_id = r.id join
     category c
     on cr.category_id = c.id;
这似乎是一个奇怪的请求,因为每个资源(至少)将获得两行,每个类别一行

此外,不要对列别名使用单引号。这些应仅用于字符串(和日期)常量。

更新2速度问题

一个速度改进(避免对每一行执行子查询)是创建一个临时表,该表的资源id与子查询匹配,并通过对其进行连接在主查询中使用

/*Create a temporary table with the ids we want (the subquery)*/
CREATE TEMPORARY TABLE Matching_Resources (INDEX(resource_id))
AS (
  SELECT
    resource_id
  FROM
    category_resource
  WHERE
    category_id IN (4,1)
  GROUP BY
    resource_id
  HAVING
    COUNT(DISTINCT category_id) = 2
);

SELECT
  r.id, r.title,
  u.name AS 'Created By',
  GROUP_CONCAT( CONCAT('[',c.name,',',c.value,',',CAST(c.id as CHAR),']') separator ' // ') AS 'Categories'
FROM
  resource r
  INNER JOIN Matching_Resources mr
    ON r.id = mr.resource_id
  INNER JOIN category_resource cr
    ON r.id = cr.resource_id
  INNER JOIN category c
    ON cr.category_id = c.id
  INNER JOIN user u
    ON r.created_by = u.id
GROUP BY r.id

更新1一些评论

在这两种情况下,您都希望类别筛选仅充当匹配资源ID的筛选器。因此,您需要将其设置为子查询,以避免影响只需要限制资源但返回所有匹配类别的主查询

因此,
其中,(..)中的r.id必须存在于两种解决方案中。您已经知道如何在其中进行过滤(因为我只使用您提供的相同代码)


符合任何提供类别的要求

SELECT 
     r.id, r.title, 
     u.name as 'Created By',
     c.name as 'Category',
     c.value,
     cr.category_id
FROM 
  resource r
  INNER JOIN category_resource cr
    ON r.id = cr.resource_id
  INNER JOIN category c
    ON cr.category_id = c.id
  INNER JOIN user u
    ON r.created_by = u.id
WHERE 
  r.id IN 
    (
      SELECT
        resource_id
      FROM
        category_resource
      WHERE
        category_id IN (6,1)
    )
演示


用于匹配所有提供类别的要求

SELECT 
     r.id, r.title, 
     u.name as 'Created By',
     c.name as 'Category',
     c.value,
     cr.category_id
FROM 
  resource r
  INNER JOIN category_resource cr
    ON r.id = cr.resource_id
  INNER JOIN category c
    ON cr.category_id = c.id
  INNER JOIN user u
    ON r.created_by = u.id
WHERE 
  r.id IN 
    (
      SELECT
        resource_id
      FROM
        category_resource
      WHERE
        category_id IN (1,4)
      GROUP BY
        resource_id
      HAVING
        COUNT(DISTINCT category_id) = 2
    )

演示在

返回较少的结果是正常的,因为您只获得了重叠,但我不是说我不希望得到较少的结果,我只是说我需要在结果中返回更多的列,就像第一次查询一样。但是,我发现问题有点复杂,请参阅我刚才的编辑谢谢你,这很有帮助。我刚刚发现,虽然我没有充分解释这个问题,请查看我的编辑,如果你能帮助…美丽!作品
SELECT 
     r.id, r.title, 
     u.name as 'Created By',
     c.name as 'Category',
     c.value,
     cr.category_id
FROM 
  resource r
  INNER JOIN category_resource cr
    ON r.id = cr.resource_id
  INNER JOIN category c
    ON cr.category_id = c.id
  INNER JOIN user u
    ON r.created_by = u.id
WHERE 
  r.id IN 
    (
      SELECT
        resource_id
      FROM
        category_resource
      WHERE
        category_id IN (1,4)
      GROUP BY
        resource_id
      HAVING
        COUNT(DISTINCT category_id) = 2
    )