Mysql从多个表中选择行

Mysql从多个表中选择行,sql,mysql,Sql,Mysql,我正在一个目录网站上工作,用户可以在那里浏览类别。类别可以包含其他类别和产品,并且产品可以属于多个类别。相关数据库架构如下所示: CREATE TABLE products ( product_id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, product_title VARCHAR(100) NOT NULL, product_status TINYINT UNSIGNED NOT NULL ); CREATE

我正在一个目录网站上工作,用户可以在那里浏览类别。类别可以包含其他类别和产品,并且产品可以属于多个类别。相关数据库架构如下所示:

CREATE TABLE products (
    product_id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
    product_title VARCHAR(100) NOT NULL,
    product_status TINYINT UNSIGNED NOT NULL
);

CREATE TABLE product_categories (
    category_id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
    parent_category_id INT UNSIGNED NOT NULL,
    category_title VARCHAR(100) NOT NULL,
    category_status TINYINT UNSIGNED NOT NULL,
    category_order INT UNSIGNED NOT NULL
);

CREATE TABLE products_categories (
    product_id INT UNSIGNED NOT NULL,
    category_id INT UNSIGNED NOT NULL,
    product_order INT UNSIGNED NOT NULL,
    PRIMARY KEY(product_id, category_id)
);
product_id      |       product_title   |       category_id     |       category_title
NULL            |       NULL            |       32              |       category foo
NULL            |       NULL            |       239             |       category bar
9391            |       product foo     |       NULL            |       NULL
325             |       product bar     |       NULL            |       NULL
我遇到的问题是,我需要使用
限制n,n
对结果进行分页:

$perpage = 20;
$start = (isset($_GET['page'])) ? (int)$_GET['page'] * $perpage : 1;
$limitsql = "LIMIT $start, $perpage";
但我不知道如何在不加入和合并结果的情况下同时选择不同的类别和产品。理想情况下,我希望得到如下结果:

CREATE TABLE products (
    product_id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
    product_title VARCHAR(100) NOT NULL,
    product_status TINYINT UNSIGNED NOT NULL
);

CREATE TABLE product_categories (
    category_id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
    parent_category_id INT UNSIGNED NOT NULL,
    category_title VARCHAR(100) NOT NULL,
    category_status TINYINT UNSIGNED NOT NULL,
    category_order INT UNSIGNED NOT NULL
);

CREATE TABLE products_categories (
    product_id INT UNSIGNED NOT NULL,
    category_id INT UNSIGNED NOT NULL,
    product_order INT UNSIGNED NOT NULL,
    PRIMARY KEY(product_id, category_id)
);
product_id      |       product_title   |       category_id     |       category_title
NULL            |       NULL            |       32              |       category foo
NULL            |       NULL            |       239             |       category bar
9391            |       product foo     |       NULL            |       NULL
325             |       product bar     |       NULL            |       NULL
我能做的最好的事情就是得到这样的东西,但这并没有真正的帮助:

product_id      |       product_title   |       category_id     |       category_title
9391            |       product foo     |       32              |       category foo
325             |       product bar     |       239             |       category bar
239             |       product foo2    |       32              |       category foo
115             |       product bar2    |       239             |       category bar
我能想到的唯一其他解决方案是查询类别中的所有子类别和产品,将它们粘贴在php数组中,并使用
array\u slice
提取当前页面。考虑到产品的数量(几千件),这不是一个非常吸引人的选择

否则,我可以查询类别的数量,并用类别的数量抵消
LIMIT
子句中的
$start
。不过,如果有超过一整页的分类,这会很混乱

以下是我当前的工作查询,它提供了上述结果:

SELECT
    p.product_id, p.product_title,
    c.category_id, c.category_title
FROM products AS p
JOIN product_categories AS c
    ON c.parent_category_id='20'
INNER JOIN products_categories AS pc
    ON p.product_id=pc.product_id
WHERE p.product_status='1' AND pc.category_id='20'
ORDER BY pc.product_order ASC
编辑 我想我已经把它和
联盟
一起工作了,我完全忘记了这一点

SELECT
    c.category_id AS row_id, c.category_title AS row_title, 1 AS is_category
FROM product_categories AS c
WHERE c.parent_category_id='20'

UNION 

SELECT
    p.product_id AS row_id, p.product_title AS row_title, 0 AS is_category
FROM products AS p
INNER JOIN products_categories AS pc
    ON p.product_id=pc.product_id
编辑2 我想工会不会像我想的那样运作。由于这两个查询都被视为单独的查询,因此我无法对整个结果应用
LIMIT
,只有每个
SELECT
。此外,似乎从每条语句中选择的列必须与另一条语句中的相应类型相同。

使用:

SELECT *
  FROM (SELECT c.category_id AS row_id, c.category_title AS row_title, 1 AS is_category
          FROM product_categories AS c
         WHERE c.parent_category_id='20'
        UNION 
        SELECT p.product_id AS row_id, p.product_title AS row_title, 0 AS is_category
          FROM products AS p
          JOIN products_categories AS pc ON p.product_id=pc.product_id) x
LIMIT x, y
使用:


另一种方法是更改模式,使类别和产品本质上是相同的

CREATE TABLE items (
    item_id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
    item_title VARCHAR(100) NOT NULL,
    item_status TINYINT UNSIGNED NOT NULL,
    category_or_item TINYINT UNSIGNED NOT NULL,
);

CREATE TABLE items_parents (
    item_id INT UNSIGNED NOT NULL,
    parent_id INT UNSIGNED NOT NULL, #points to itemid
    item_order INT UNSIGNED NOT NULL,
    PRIMARY KEY(item_id, parent_id)
);

然后,您的查询是平面的,您可以按类别或项目对其进行排序,以便首先显示类别。

另一种方法是更改模式,使类别和产品本质上相同

CREATE TABLE items (
    item_id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
    item_title VARCHAR(100) NOT NULL,
    item_status TINYINT UNSIGNED NOT NULL,
    category_or_item TINYINT UNSIGNED NOT NULL,
);

CREATE TABLE items_parents (
    item_id INT UNSIGNED NOT NULL,
    parent_id INT UNSIGNED NOT NULL, #points to itemid
    item_order INT UNSIGNED NOT NULL,
    PRIMARY KEY(item_id, parent_id)
);
然后,您的查询是平面的,您可以按类别或项目对其进行排序,以便首先显示类别