【问题标题】:Mysql get results from one table based on another with joinMysql 通过连接从一个表中获取基于另一个表的结果
【发布时间】:2019-02-27 10:08:32
【问题描述】:

我有 2 张桌子:

$sql = "CREATE TABLE $media_table (
            `id` int(11) NOT NULL AUTO_INCREMENT,
            `type` varchar(50) NOT NULL,
            `title` varchar(255) DEFAULT NULL,
            `description` varchar(2000) DEFAULT NULL,
            `playlist_id` int(11) NOT NULL,
            PRIMARY KEY (`id`),
            INDEX `playlist_id` (`playlist_id`),
        ) $charset_collate;";

$sql = "CREATE TABLE $taxonomy_table (
                `id` int(11) NOT NULL AUTO_INCREMENT,
                `type` varchar(10) NOT NULL,
                `title` varchar(500) NOT NULL,
                `media_id` int(11) NOT NULL,
                `playlist_id` int(11) NOT NULL,
                PRIMARY KEY (`id`),
                INDEX `media_id` (`media_id`),
                CONSTRAINT `mvp_taxonomy_ibfk_1` FOREIGN KEY (`media_id`) REFERENCES {$media_table} (`id`) ON DELETE CASCADE ON UPDATE CASCADE
            ) $charset_collate;";

假设我想从 media_table 中选择所有行,其中 playlist_id=5 并从 taxonomy_table="sport, football" 中选择标题。

我可以运行 2 个查询,首先从 taxonomy_table where title="..." AND playlist_id="5" 获取所有 media_id,然后第二个查询从 media_table WHERE id IN (ids) 中选择所有行。

这可能属于某种 JOIN 查询吗?

我试过了,但没有得到想要的结果:

$query = "SELECT * FROM {$media_table} 
        INNER JOIN {$taxonomy_table} 
        ON {$media_table}.id = {$taxonomy_table}.media_id 
        WHERE {$taxonomy_table}.type='tag' AND {$taxonomy_table}.title IN ($arg) AND {$taxonomy_table}.playlist_id=%d
        ORDER BY {$media_table}.order_id";

似乎它将两个表中的所有列混合到结果中,但我只想从 media_table 中检索具有分类表中标题的行。

【问题讨论】:

标签: mysql join


【解决方案1】:

似乎它将两个表中的所有列混合到结果中,但我只想从 media_table 中检索具有分类表中标题的行。

原因是连接使您能够从两个表中选择数据。 在这种情况下,技巧是将星号 (*) 更改为特定列或使用星号前缀。

使用前缀的例子:

$query = "SELECT {$media_table}.* FROM {$media_table} 
INNER JOIN {$taxonomy_table} 
ON {$media_table}.id = {$taxonomy_table}.media_id 
    `WHERE {$taxonomy_table}.type='tag' AND {$taxonomy_table}.title IN ($arg) AND` {$taxonomy_table}.playlist_id=%d
ORDER BY {$media_table}.order_id";

$query = "SELECT t1.* FROM {$media_table} t1
INNER JOIN {$taxonomy_table} t2
ON t1.id = t2.media_id 
WHERE t2.type='tag' AND t2.title IN ($arg) AND t2.playlist_id=%d
ORDER BY t1.order_id";

更新: 您在评论中提出了两个“新”问题: 从您的用例中,我看不出有任何理由在这里使用联接。

1:从 media_table 中检索具有所有必需标题的行 分类表

从我的角度来看,仅使用 SQL 没有简单的解决方案(SQL 中可能非常棘手的字符串操作除外)。 最简单的解决方案可能是这样的:

$countTitles = count(explode(",", $args))
$query = "SELECT media_id from {$media_table} WHERE $countTitles = (
SELECT count(media_id) from {$taxonomy_table} WHERE type='tag' AND title IN ($arg) AND playlist_id=%d
)"

2:从 media_table 中检索任何所需标题的行 分类表。

这只是一个简单的子句。

$query = "SELECT * FROM {$media_table}
WHERE media_id IN (
SELECT media_id FROM {$taxonomy_table} WHERE type='tag' AND title IN ($arg) AND playlist_id=%d
)
";

【讨论】:

  • 仍然不太正确,这将返回一个(相同)行两次,因为它在分类表中具有两个值。我不想要那个。我将如何 1:从 media_table 中检索具有 taxonomy_table 中所有必需标题的行,2:从 media_table 中检索具有 taxonomy_table 中任何必需标题的行。
  • 连接总是会在连接子句中的每个“匹配”中为您提供一行(除非进一步使用 whereclause 或 distinct)。当您想要同时获取两个表中的数据时,通常会使用连接。
  • 所以你的第二个问题的解决方案是例如select * from {$media_table} where media_id in (select media_id from {$taxonomy_table} where title in ($arg))
  • 要解决您的第一个问题,您需要更多的逻辑,SQL 并不是真正用于在一个查询中解决此类问题。一种选择可能是使用您的编程语言来帮助您,在 PHP 中可能是这样的: select * from {$media_table} where " .count(explode(',', $args)) + 1 . " = (select count(media_id) from {$taxonomy_table} where title in ($arg) [+ other filter criteria you need])
  • 如果我只使用我在帖子中提到的 2 个查询,这会显着变慢吗?因为它看起来更容易/易于阅读。
【解决方案2】:

在嵌套/连接查询中使用联合而不是连接

    $query = "SELECT * FROM {$media_table} 
            INNER JOIN {$taxonomy_table} 
            ON {$media_table}.id = {$taxonomy_table}.media_id 
            WHERE {$taxonomy_table}.type='tag' AND {$taxonomy_table}.title IN ($arg) AND {$taxonomy_table}.playlist_id=%d
            ORDER BY {$media_table}.order_id 
union SELECT * FROM {$media_table}
WHERE media_id IN (
SELECT media_id FROM {$taxonomy_table} WHERE type='tag' AND title IN ($arg) AND playlist_id=%d
)
";

【讨论】:

  • 你能举个例子吗?
  • 我添加了一个经过编辑的示例。您可以试试这个并将结果分组以获得独特的结果集
  • 这是一个查询?我收到错误:UNION 和 ORDER BY 的使用不正确
  • 你可以把第一个查询中的order by子句去掉,放在最后作为整体输出
猜你喜欢
  • 1970-01-01
  • 2014-10-20
  • 1970-01-01
  • 1970-01-01
  • 2019-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多