这是我的问题:我有三个代表多对多关系的表,看起来像是这样:
表格产品
PRODUCT_ID
product_price等(每种产品的基本信息相同)
表格规格
spec_id
spec_name
table products_specifications
PRODUCT_ID
spec_id
内容
我的目标是按照规格选择产品(一个以及多个),所以我使用了以下查询:
SELECT *
FROM products p
JOIN products_specifications ps ON ps.products_id = p.products_id
JOIN specifications s ON s.spec_id = ps.spec_id
WHERE s.spec_name IN (<names of specs>)
AND pts.content IN (<content of specs>)
GROUP BY p.products_id
HAVING COUNT(DISTINCT s.specifications_name) = <count of specs name>
AND COUNT(DISTINCT ps.content) = <count of specs content>
我想获得属于所有产品的所有规范,但是此查询仅返回其中一个规范(用于进行查询的规范)。
specifications.content列包含我想用于查询产品(或多个)的值(包含在其所有规范中)。可以在specifications.spec_name表中找到这些规范的名称。为了确保查询不会检索另一行中可能相同但内容不同的内容,我还会对规范名称进行WHERE IN。
是否可以进行选择特定规格的查询,还可以返回所选产品的所有规格?
我已经想过并试验过UNIONS和SUBQUERIES。但是我无法生成足够的查询。我认为子查询可能是进入的方向。使用返回的product_id的第二个查询不是可能的,因为它必须能够按照每个产品的任何规范来订购查询。
答案 0 :(得分:0)
SELECT *
FROM products_specifications
GROUP BY product_id;
答案 1 :(得分:0)
我并不完全清楚你要做什么,但如果我可以重申你的目标:你想选择具有给定“规格”的“产品”,但对于那些“产品”,选择他们所有的“规格” ”。您是否尝试过两次加入“products_specifications”和“specifications”表:
SELECT *
FROM products p
JOIN product_specifications ps1 ON ps1.products_id = p.products_id
JOIN specifications s1 ON s1.spec_id = ps1.spec_id
JOIN product_specifications ps2 ON ps2.products_id = p.products_id
JOIN specifications s2 ON s2.spec_id = ps2.spec_id
WHERE s.spec_name IN (<names of specs>)
AND pts.content IN (<content of specs>)
GROUP BY p.products_id
HAVING COUNT(DISTINCT s.specifications_name) = <count of specs name>
AND COUNT(DISTINCT pts.content) = <count of specs content>
注意s1&amp; s2,和ps1&amp; PS2。 s1&amp; ps1将允许您选择,但您可以看到所有使用s2&amp; PS2。你的WHERE
子句中也有'pts',但没有在FROM
部分中将其指定为表格,我假设你打算'ps'?
答案 2 :(得分:0)
您的查询似乎正确无误。它将返回符合您条件的产品的所有产品详细信息(它们适用于所有(<names of specs>)
和所有(<content of specs>)
)。顺便使用SELECT p.*
会更好,因为您按p.products_id
进行分组。从其他列中获得的结果并不真正有用。
现在,如果您想获得这些产品,此外,获取这些产品的所有规格(不仅是两个列表中的spcs),请使用:
(更新>已添加GROUP BY pd.products_id
和GROUP_CONCAT()
,以便将多行产品的信息收集到一起)
SELECT pd.*
, GROUP_CONCAT( ps.content
ORDER BY ps.spec_id )
, GROUP_CONCAT( s.spec_name
ORDER BY ps.spec_id )
, GROUP_CONCAT( CONCAT(s.spec_name,'-',ps.content)
ORDER BY ps.spec_id )
FROM
( SELECT p.*
FROM products p
JOIN products_specifications ps ON ps.products_id = p.products_id
JOIN specifications s ON s.spec_id = ps.spec_id
WHERE s.spec_name IN (<names of specs>)
AND ps.content IN (<content of specs>)
GROUP BY p.products_id
HAVING COUNT(DISTINCT s.specifications_name) = <count of specs name>
AND COUNT(DISTINCT ps.content) = <count of specs content>
) AS pd
JOIN
products_specifications ps ON ps.products_id = pd.products_id
JOIN
specifications s ON s.spec_id = ps.spec_id
GROUP BY pd.products_id
答案 3 :(得分:0)
有了您的澄清,Ruben,我想我了解数据库结构以及您现在要问的内容。我将从观察开始,您需要使用什么来查询数据库是一个或多个对的specifications.spec_name和products_specifications.content。正如您在问题中所述,您希望能够使用其中一个或多个来查询满足所有条件的一组产品。
要了解为什么只有spec_name和内容的成对组合是合理的,请考虑一个示例,其中产品是汽车,一些规格是各种组件的颜色(例如body_color,interior_color,racing_stripe_color)。如果您搜索车身颜色为红色且内部颜色为黑色的车辆,但查询不会成对关联spec_name和内容,那么您还将检索车身颜色为黑色且内部颜色为红色的车辆,这不是您想要的。如果您的任何规范都将数字作为值,则同样适用。
我的回答使用子查询来返回将用于生成最终输出的product_id值,但也可以使用其他连接来完成。如果使用子查询的查询太慢,您可能需要尝试其他版本。我也将使用“select *”,虽然我强烈建议不要在生产环境中这样做(你应该列出列),因为如果数据库结构发生变化,事情往往会更容易破坏。您还将获得一些具有重复值的列,这些列可以通过正确的列列表来消除。我假设product_id和spec_id分别在产品和规格表中是唯一的,并且product_id和spec_id的每个组合在products_specifications表中最多出现一次。
select * from (
select p1.product_id as product_id from products as p1
join products_specifications as ps1 on p1.product_id = ps1.product_id
join specifications as s1 on ps1.spec_id = s1.spec_id
where <selection conditions>
group by p1.product_id
having count(s1.spec_id) = <number of selection conditions>
) pp
join products as p on pp.product_id = p.product_id
join products_specifications as ps on p.product_id = ps.product_id
join specifications as s on ps.spec_id = s.spec_id
order by p.product_id, s.spec_name;
&lt;选择条件&gt;将采用以下形式:
(s1.spec_name = 'spec1' and ps1.content = 'spec1value')
or (s1.spec_name = 'spec2' and ps1.content = 'spec2value')
or ...
对于要在查询中使用的spec_name,内容对。您需要手动或在调用代码中生成查询的该部分。您需要确保&lt;选择条件的数量&gt;以相同的方式等于条件的数量。