在没有CROSS JOIN的情况下显示多对多主表中的所有行

时间:2015-03-10 03:27:35

标签: sql-server tsql

这是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

4 个答案:

答案 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"。