保持SQL干

时间:2010-02-21 04:07:18

标签: sql mysql dry

这是我正在运行的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个不同的查询我正在使用相同的三行运行时,问题会更加严重。

3 个答案:

答案 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的