这是我正在运行的MySQL查询:
-- get the sid of every supplier who does not supply both a red and green part
SELECT Suppliers.sid, Parts.color
FROM Suppliers
JOIN Catalog ON Catalog.sid = Suppliers.sid
JOIN Parts ON Parts.pid = Catalog.pid
WHERE Suppliers.sid NOT IN (
SELECT Suppliers.sid
FROM Suppliers
JOIN Catalog ON Catalog.sid = Suppliers.sid
JOIN Parts ON Parts.pid = Catalog.pid
WHERE Parts.color IN ('red', 'green')
GROUP BY Suppliers.sid
HAVING COUNT(DISTINCT Parts.color) = 2
)
ORDER BY Suppliers.sid DESC;
如您所见,重复两次:
FROM Suppliers
JOIN Catalog ON Catalog.sid = Suppliers.sid
JOIN Parts ON Parts.pid = Catalog.pid
我只能申报一次,并参考两次?或者这是否表明我的整个查询都存在缺陷?
当我有15个不同的查询我正在使用相同的三行运行时,问题会更加严重。
答案 0 :(得分:5)
如果您要在整个系统中继续使用表关系,那么您想要查看的内容称为view。
答案 1 :(得分:0)
我认为可以在MySQL中使用更多ANSI解决方案:
SELECT X.sid, X.color
FROM (SELECT Catalog.sid, parts.color,
count(distinct parts.color) as distinct_color_count
from Catalog
inner jOIN Parts
ON Parts.pid = Catalog.pid
where parts.color in ("red", "green")
group by catalog.sid, parts.color)
) x
where x.distinct_color_count = 2
order by x.sid desc
您不会从供应商中提取任何内容,而是必须存在于目录中,因此请使用Catalog.sid。
嵌套select语句,以便获得distinct_color_count,以便您可以在以下步骤中对其进行过滤。如果你试试这个:
SELECT Catalog.sid, parts.color,
count(distinct parts.color)
from Catalog
inner join Parts
ON Parts.pid = Catalog.pid
where parts.color in ("red", "green")
having count(distinct parts.color) = 2
group by catalog.sid, parts.color
order by catalog.sid ;
它不起作用,因为每行只有一种不同的颜色。
答案 2 :(得分:0)
您可以使用这样的VIEW来干扰最常见的查询(尤其是常见的连接):
CREATE OR REPLACE ALGORITHM=MERGE VIEW Suppliers_Catalog_Parts
AS
select *
FROM Suppliers
JOIN Catalog ON Catalog.sid = Suppliers.sid
JOIN Parts ON Parts.pid = Catalog.pid;
您可能希望将*更改为特定列以避免ID名称冲突。
有几点需要注意。
首先,对于没有where子句的视图,ALWAYS将算法指定为MERGE,以便视图存储为查询,然后在运行时与SQL合并;否则它可以被评估为临时表(这对于像这样的通用视图可能是灾难性的)。
其次,某些查询无法作为VIEW创建 - 特别是如果from子句包含子查询。也有解决方法。
如果您想了解更多内容,我在这里写一篇关于如何编写DRY SQL的系列文章: http://blog.gruffdavies.com/2014/08/23/how-to-write-dry-sql-in-mysql-part-1-views/
HTH
Gruff的