我有一个需要简化的工作查询。
原因是我需要对其进行大量扩展以涵盖实际应用。对于每个条件(Pos = xxx AND Indata = yyy),当前查询的大小加倍,并且我有很多条件。此外,ON子句将包含比示例中更多的条件....
真正的应用程序将有大约20个Pos / Indata条件(这里只有3个)和其他20个必须匹配的字段(这里只有1个)。
查询的作用,在“伪代码”中解释:
find all rows with (Pos=xx1 AND Indata=yy1) as t1
union
all rows with (Pos=xx2 AND Indata=yy2) as t2
then join t1 and t2 to keep only rows where other fields match (t1.fields=t2.fields OR t1.fields=* OR t2.fields=*)
you could store this in a temp table temp1
then find all rows with (Pos=xx3 AND Indata=yy3) as t3
union
temp1
then join t3 and temp1 to keep only rows where other fields match (t3.fields=temp1.fields OR t3.fields=* OR temp1.fields=*)
you could store this in a temp table temp2
then find all rows with (Pos=xx4 AND Indata=yy4) as t4
union
temp2
join t4 and temp4 to keep only rows where other fields match (t4.fields=temp4.fields OR t4.fields=* OR temp4.fields=*)
you could store this in a temp table temp2
等等....我基本上想找到所有行表“代码”与某些Pos和Indata,其中大多数其他字段相互匹配....一个可能的解决方案可能是临时表加上一点PHP作为在上面的伪代码....但它只能在SQL中解决....
SELECT t15.* FROM (
(
SELECT DISTINCT t6.* FROM (
(
SELECT t5.* FROM (
(
SELECT DISTINCT t1.* FROM (
(SELECT * FROM codes WHERE (Pos = 10 AND Indata = 'Rexroth')) AS t1
JOIN (
(SELECT * FROM codes WHERE (Pos = 30 AND Indata = '%Mineralolja')) AS t2
) ON (t1.Manufacturer = t2.Manufacturer OR t1.Manufacturer='*' OR t2.Manufacturer='*')
)
) UNION (
SELECT DISTINCT t4.* FROM (
(SELECT * FROM codes WHERE (Pos = 10 AND Indata = 'Rexroth')) AS t3
JOIN (
(SELECT * FROM codes WHERE (Pos = 30 AND Indata = '%Mineralolja')) AS t4
) ON (t3.Manufacturer = t4.Manufacturer OR t3.Manufacturer='*' OR t4.Manufacturer='*')
)
)
) AS t5
) AS t6
JOIN (
(
SELECT * FROM codes WHERE (Pos = 70 AND Indata = '28 cm3')
) AS t7
) ON (t7.Manufacturer = t6.Manufacturer OR t7.Manufacturer='*' OR t6.Manufacturer='*')
)
) UNION (
SELECT DISTINCT t14.* FROM (
(
SELECT t12.* FROM (
(
SELECT DISTINCT t8.* FROM (
(SELECT * FROM codes WHERE (Pos = 10 AND Indata = 'Rexroth')) AS t8
JOIN (
(SELECT * FROM codes WHERE (Pos = 30 AND Indata = '%Mineralolja')) AS t9
) ON (t9.Manufacturer = t8.Manufacturer OR t9.Manufacturer='*' OR t8.Manufacturer='*')
)
) UNION (
SELECT DISTINCT t11.* FROM (
(SELECT * FROM codes WHERE (Pos = 10 AND Indata = 'Rexroth')) AS t10
JOIN (
(SELECT * FROM codes WHERE (Pos = 30 AND Indata = '%Mineralolja')) AS t11
) ON (t11.Manufacturer = t10.Manufacturer OR t11.Manufacturer='*' OR t10.Manufacturer='*')
)
)
) AS t12
) AS t13
JOIN (
(
SELECT * FROM codes WHERE (Pos = 70 AND Indata = '28 cm3')
) AS t14
) ON (t13.Manufacturer = t14.Manufacturer OR t13.Manufacturer='*' OR t14.Manufacturer='*')
)
)
) AS t15
我刚刚用temp表重写了它,似乎至少更容易阅读:
CREATE TEMPORARY TABLE temp
SELECT * FROM codes WHERE (Pos = 10 AND Indata = 'Rexroth');
CREATE TEMPORARY TABLE temp2
SELECT DISTINCT t1.* FROM (
(SELECT * FROM temp) AS t1
JOIN (
(SELECT * FROM codes WHERE (Pos = 30 AND Indata = '%Mineralolja')) AS t2
) ON (t1.Manufacturer = t2.Manufacturer OR t1.Manufacturer='*' OR t2.Manufacturer='*')
);
INSERT INTO temp2
SELECT DISTINCT t2.* FROM (
(SELECT * FROM temp) AS t1
JOIN (
(SELECT * FROM codes WHERE (Pos = 30 AND Indata = '%Mineralolja')) AS t2
) ON (t1.Manufacturer = t2.Manufacturer OR t1.Manufacturer='*' OR t2.Manufacturer='*')
);
DROP TABLE temp;
ALTER TABLE temp2 RENAME temp;
CREATE TEMPORARY TABLE temp2
SELECT DISTINCT t1.* FROM (
(SELECT * FROM temp) AS t1
JOIN (
(SELECT * FROM codes WHERE (Pos = 70 AND Indata = '28 cm3')) AS t2
) ON (t1.Manufacturer = t2.Manufacturer OR t1.Manufacturer='*' OR t2.Manufacturer='*')
);
INSERT INTO temp2
SELECT DISTINCT t2.* FROM (
(SELECT * FROM temp) AS t1
JOIN (
(SELECT * FROM codes WHERE (Pos = 70 AND Indata = '28 cm3')) AS t2
) ON (t1.Manufacturer = t2.Manufacturer OR t1.Manufacturer='*' OR t2.Manufacturer='*')
);
SELECT * FROM temp2;
答案 0 :(得分:1)
这里有很多关于存储过程和临时表的说法 - 正如你自己建议的那样。
例如,即使是现在你的SQL也很难阅读:我看着它并立刻想到“太长了,真的不想读”: - )
过程和工作台可以让未来的开发人员更容易阅读和扩展生活 - 自己包括在6个月的时间内!
您还可以从procs和工作表中获得性能优势:您可以将索引放在工作表上,一次调试一个proc,看看瓶颈在哪里等等。
我想我推荐:赞成使用单个查询的“优雅”的可读性和可扩展性,如果在任何一种方法中都可以认为性能或多或少相等。
答案 1 :(得分:0)
正如布莱恩所说:
......太长了,真的不想看了..
但是我试过,我认为你的“Where's”总会有这样的结构:
SELECT * FROM codes WHERE Pos = number AND/LIKE Indata =/% 'somethin' and some how "Manufactor"
所以我会尝试“转动选择”并使用主键 - 很难解释 -
我尝试:第一步:
Select PK from codes where CRITERIA1
union (all)*
Select PK from codes where CRITERIA2
union (all)*
Select PK from codes where CRITERIA3
所以你得到一个漂亮的选择和一个只有一个col的结果集:主键(PK)[*表示如果“uninon”或“uninon all”表现更好,它取决于你的行数]
用
来解决这个问题select [distinct] * from codes where codes.pk in (
Select PK from codes where CRITERIA1
union
....
till CRITERIA42
)