这是sqlfiddle:
http://sqlfiddle.com/#!6/cd936/5
这是查询的其余部分:
CREATE TABLE Farmers (
FarmerName NVARCHAR (50)
);
CREATE TABLE Animals (
AnimalName NVARCHAR (50)
);
CREATE TABLE FarmerAnimals (
FarmerName NVARCHAR (50)
, AnimalName NVARCHAR (50)
, Qty INT
);
INSERT Farmers (FarmerName) VALUES ('Jane'), ('Andrew'), ('Bob')
INSERT Animals (AnimalName) VALUES ('Goat'), ('Horse'), ('Elephant')
INSERT FarmerAnimals (FarmerName, AnimalName, Qty) VALUES ('Jane', 'Goat', 10), ('Jane', 'Elephant', 3), ('Jane', 'Elephant', 1), ('Andrew', 'Horse', 5), ('Bob', 'Goat', 1), ('Bob', 'Goat', 1)
SELECT
f.FarmerName
, a.AnimalName
, Qty = SUM (ISNULL (fa.qty, 0))
FROM
Farmers f
CROSS JOIN Animals a
LEFT JOIN FarmerAnimals fa ON
fa.FarmerName = f.FarmerName
AND fa.AnimalName = a.AnimalName
GROUP BY f.FarmerName, a.AnimalName
有没有办法重写SELECT
查询而不使用CROSS JOIN
?
答案 0 :(得分:1)
你可以通过常规INNER JOIN
来做到这一点,但是在幕后可能接近100%这两个查询将提供相同的执行计划:
SELECT
f.FarmerName
, a.AnimalName
, Qty = SUM (ISNULL (fa.qty, 0))
FROM
Farmers f
INNER JOIN Animals a ON 1 = 1
LEFT JOIN FarmerAnimals fa ON
fa.FarmerName = f.FarmerName
AND fa.AnimalName = a.AnimalName
GROUP BY f.FarmerName, a.AnimalName
答案 1 :(得分:0)
您可以使用以下代替交叉联接。
这 动物a 内联盟农民f 在f.FarmerName<> a.AnimalName
答案 2 :(得分:0)
如果您需要所有农民和动物展示即使他们没有FarmerAnimal记录,您也必须使用CROSS JOIN。否则,正常的JOIN会做,但只显示在FarmerAnimals中有记录的农民/动物
答案 3 :(得分:0)
我不确定你的SQLFiddle可能会显示什么;它不会为我加载。但是如果你想要所有农民姓名和所有动物名称,无论是否在#34; FarmerAnimals"中都有匹配的行,我都会在标准SQL中写这个。 (我在Farmers和Animals中添加了另一行,因此我们可以清楚地看到外连接的效果。)
select f.FarmerName, a.AnimalName, sum(coalesce(fa.qty, 0)) as TotalQty
from Farmers f
full outer join FarmerAnimals fa
on f.FarmerName = fa.FarmerName
full outer join Animals a
on a.AnimalName = fa.AnimalName
group by f.FarmerName, a.AnimalName
order by f.FarmerName, a.AnimalName;
FarmerName AnimalName TotalQty -- Andrew Horse 5 Bob Goat 2 Jane Elephant 4 Jane Goat 10 Joe Bob 0 Horse-sized duck 0
而且,为了在SQL Server中完成这项工作,我认为您需要做的就是将表达式sum(coalesce(fa.qty, 0)) as TotalQty
替换为sum(isnull(fa.qty, 0)) as TotalQty
。 SQL Server 2005+支持完全外连接。
我没有办法测试完全外连接是否避免SQL Server中的嵌套循环(评论说你感兴趣),但PostgreSQL的查询规划器使用&#34 ; Hash Full Join"。