Mysql 从表中选择值跨多行的位置

Mysql 从表中选择值跨多行的位置,mysql,sql,Mysql,Sql,我有一个将产品映射到类别的表。每个产品可以属于多个类别,因此一个产品可以有多个具有不同类别ID的行。它看起来像这样: CREATE TABLE `products_mid` ( `id` int(11) UNSIGNED NOT NULL, `product_id` int(11) UNSIGNED NOT NULL DEFAULT '0', `category_id` int(11) UNSIGNED NOT NULL DEFAULT '0' ) ENGINE=MyISAM DEF

我有一个将产品映射到类别的表。每个产品可以属于多个类别,因此一个产品可以有多个具有不同类别ID的行。它看起来像这样:

CREATE TABLE `products_mid` (
  `id` int(11) UNSIGNED NOT NULL,
  `product_id` int(11) UNSIGNED NOT NULL DEFAULT '0',
  `category_id` int(11) UNSIGNED NOT NULL DEFAULT '0'
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
SELECT product_id
GROUP BY product_id
HAVING SUM(CASE WHEN category_id=1 THEN 1 ELSE 0 END) > 0
   AND SUM(CASE WHEN category_id=2 THEN 1 ELSE 0 END) > 0
   AND SUM(CASE WHEN category_id=3 THEN 1 ELSE 0 END) > 0
select product_id from products_mid
where
category_id in (1,2,3)
group by product_id
having count(distinct category_id)=3

如果我想得到一个属于类别a的所有产品ID的列表,这很简单,但是有没有一种方法可以尽可能简单地得到属于类别a、B和C的所有产品ID?

更好的方法是使用have子句,而不是where子句。按product_id分组,并选择三个类别中计数均为非零的行,如下所示:

CREATE TABLE `products_mid` (
  `id` int(11) UNSIGNED NOT NULL,
  `product_id` int(11) UNSIGNED NOT NULL DEFAULT '0',
  `category_id` int(11) UNSIGNED NOT NULL DEFAULT '0'
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
SELECT product_id
GROUP BY product_id
HAVING SUM(CASE WHEN category_id=1 THEN 1 ELSE 0 END) > 0
   AND SUM(CASE WHEN category_id=2 THEN 1 ELSE 0 END) > 0
   AND SUM(CASE WHEN category_id=3 THEN 1 ELSE 0 END) > 0
select product_id from products_mid
where
category_id in (1,2,3)
group by product_id
having count(distinct category_id)=3

上面的语句选择了属于ID为1、2和3的所有三个类别的产品的产品ID。

更好的方法是使用HAVING子句,而不是WHERE子句。按product_id分组,并选择三个类别中计数均为非零的行,如下所示:

CREATE TABLE `products_mid` (
  `id` int(11) UNSIGNED NOT NULL,
  `product_id` int(11) UNSIGNED NOT NULL DEFAULT '0',
  `category_id` int(11) UNSIGNED NOT NULL DEFAULT '0'
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
SELECT product_id
GROUP BY product_id
HAVING SUM(CASE WHEN category_id=1 THEN 1 ELSE 0 END) > 0
   AND SUM(CASE WHEN category_id=2 THEN 1 ELSE 0 END) > 0
   AND SUM(CASE WHEN category_id=3 THEN 1 ELSE 0 END) > 0
select product_id from products_mid
where
category_id in (1,2,3)
group by product_id
having count(distinct category_id)=3
上面的语句选择属于ID为1、2和3的所有三个类别的产品的产品ID。

另一种方式:

SELECT product_id
FROM products_mid
WHERE category_id IN (1, 2, 3)
GROUP BY product_id
HAVING COUNT(DISTINCT category_id) = 3
这将找到类别1到3中的所有产品,尽管产品也可能属于其他类别。如果您想要的产品只属于类别1到类别3,而不属于其他类别,那么我们必须重新表述查询。

另一种方式:

SELECT product_id
FROM products_mid
WHERE category_id IN (1, 2, 3)
GROUP BY product_id
HAVING COUNT(DISTINCT category_id) = 3

这将找到类别1到3中的所有产品,尽管产品也可能属于其他类别。如果您想要的产品只属于类别1到类别3,而不属于其他类别,那么我们必须重新表述查询。

它将是这样的:

CREATE TABLE `products_mid` (
  `id` int(11) UNSIGNED NOT NULL,
  `product_id` int(11) UNSIGNED NOT NULL DEFAULT '0',
  `category_id` int(11) UNSIGNED NOT NULL DEFAULT '0'
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
SELECT product_id
GROUP BY product_id
HAVING SUM(CASE WHEN category_id=1 THEN 1 ELSE 0 END) > 0
   AND SUM(CASE WHEN category_id=2 THEN 1 ELSE 0 END) > 0
   AND SUM(CASE WHEN category_id=3 THEN 1 ELSE 0 END) > 0
select product_id from products_mid
where
category_id in (1,2,3)
group by product_id
having count(distinct category_id)=3

它将是这样的:

CREATE TABLE `products_mid` (
  `id` int(11) UNSIGNED NOT NULL,
  `product_id` int(11) UNSIGNED NOT NULL DEFAULT '0',
  `category_id` int(11) UNSIGNED NOT NULL DEFAULT '0'
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
SELECT product_id
GROUP BY product_id
HAVING SUM(CASE WHEN category_id=1 THEN 1 ELSE 0 END) > 0
   AND SUM(CASE WHEN category_id=2 THEN 1 ELSE 0 END) > 0
   AND SUM(CASE WHEN category_id=3 THEN 1 ELSE 0 END) > 0
select product_id from products_mid
where
category_id in (1,2,3)
group by product_id
having count(distinct category_id)=3
使用intersect运算符查找三个单独查询的公共值

select product_id from products_mid where category_id = 1
intersect
select product_id from products_mid where category_id = 2
intersect
select product_id from products_mid where category_id = 3
使用intersect运算符查找三个单独查询的公共值

select product_id from products_mid where category_id = 1
intersect
select product_id from products_mid where category_id = 2
intersect
select product_id from products_mid where category_id = 3

注意:intersect在MySQL中不可用,因此对于这个特定问题不是一个好答案,但我保留它是因为几乎所有其他数据库系统都支持它。注意:intersect在MySQL中不可用,因此对于这个特定问题不是一个好答案,但我保留它是因为几乎所有其他数据库系统都支持它。此表中的“代理项id”列似乎是多余的,因为您在其余列上似乎具有令人满意的自然键。此表中的“代理项id”列似乎是多余的,因为您似乎在其余列上具有完全令人满意的自然键。