在我们的数据库中,客户可以拥有任意数量的司机,任意数量的车辆,任意数量的存储位置,这些位置的任意数量的建筑物,任意数量的评论等等。我需要一个返回所有客户信息的查询,现在查询类似于:
SELECT *
FROM Customer c
INNER JOIN Driver d ON c.ID = d.CustomerID
INNER JOIN Vehicle v ON c.ID = v.CustomerID
客户越多,结果越大,并且由于在此处创建了笛卡尔积,因此它呈指数级增长。 3个驱动程序,3个vechiles创建9行,与我们的真实数据相比,这是一个非常小的例子。实际上,我们有10个不同的表,可以根据需要为每个客户保留尽可能多的行。每个客户每个表至少有2-7行标准。我们已经返回了多达60,000,000多行(在10个不同的表中各有6个项目,6 ^ 10 = 60,466,176),对于我们的目的,如果我们只能 坚持 每个表中的6行。
所以在较小的例子中,如果1个客户有2辆车和3个司机而另一个客户有2辆车和1个司机我想要一个看起来像的结果集:
CustomerID | DriverID | VehicleID
1 | 1 | 1
1 (or NULL) | 2 | 2
1 (or NULL) | NULL | 3
2 | 3 | 4
2 (or NULL) | 4 | NULL
相反,我们在CustomerID上将每个表连接在一起的查询如下所示:
CustomerID | DriverID | VehicleID
1 | 1 | 1
1 | 1 | 2
1 | 1 | 3
1 | 2 | 1
1 | 2 | 2
1 | 2 | 3
2 | 3 | 4
2 | 4 | 4
真的,我想做的只是:
SELECT * FROM Driver
SELECT * FROM Vehicle
因为我们对数据的所有操作都循环遍历行并格式化文档中的信息。列出所有车手,然后列出所有车辆。在我们不必要的情况下进行这种疯狂的巨大连接是没有意义的,但它只是一个任意的要求,它必须返回一个拒绝倾听理性的顽固上级的结果集中的所有数据。由于列不同,因此不可能使用UNION。我只是希望有一种方法可以将它们水平而不是垂直地粘在一起。
另外,我正在使用Microsoft SQL Server。
答案 0 :(得分:3)
这是一个丑陋的黑客,但你知道你正确的解决方案正如你所说:
SELECT * FROM Driver
SELECT * FROM Vehicle
相反,您可以使用联合查询并清除其他表中的列,只需使用设置列的类型和名称的查询启动它,并使用false coldition,因此它不会返回行:< / p>
SELECT 1 AS DriverID, "" AS DriverName, 1 AS VehicleID, "" AS VehicleName WHERE 1=0
UNION SELECT DriverID, DriverName, NULL, NULL FROM Driver
UNION SELECT NULL, NULL, VehicleID, VehicleName FROM Driver
真的,真的很糟糕的代码!继续为你的上司工作以提供更好的解决方案。
答案 1 :(得分:1)
以下是我的表现方式。而不是:
SELECT *
FROM Customer c
INNER JOIN Driver d ON c.ID = d.CustomerID
INNER JOIN Vehicle v ON c.ID = v.CustomerID
我在做:
WITH CustomerCTE AS
(
SELECT 1 ROW_NUM, ID
FROM Customer
),
DriverCTE AS
(
SELECT ROW_NUMBER() OVER (PARTITION BY CustomerID ORDER BY ID) ROW_NUM, *
FROM Driver
),
VehicleCTE AS
(
SELECT ROW_NUMBER() OVER (PARTITION BY CustomerID ORDER BY ID) ROW_NUM, *
FROM Vehicle
)
SELECT *
FROM CustomerCTE c
FULL OUTER JOIN DriverCTE d ON c.ID = d.CustomerID AND c.ROW_NUM = d.ROW_NUM
FULL OUTER JOIN VehicleCTE v ON d.CustomerID = v.CustomerID AND d.ROW_NUM = v.ROW_NUM
ORDER BY
CASE WHEN c.ID IS NOT NULL THEN c.ID ELSE
CASE WHEN d.CustomerID IS NOT NULL THEN d.CustomerID ELSE
v.CustomerID
END
END,
CASE WHEN c.ROW_NUM IS NOT NULL THEN c.ROW_NUM ELSE
CASE WHEN d.ROW_NUM IS NOT NULL THEN d.ROW_NUM ELSE
v.ROW_NUM
END
END
现在,如果客户有3个司机和3辆车,我会得到3行而不是9行。这使得看起来每个驾驶员都与3辆车中的1辆相关联,但事实并非如此。同样,这是一个糟糕的设计,但有必要减少我给出的不合理限制返回的行数。
它似乎比webturner的答案更多的工作,但在我的实际情况中,我必须加入10个不同的表,超过500列,这样做的工作要少得多,而不是明确命名所有500列并填写所有每个表的剩余列的值为NULL。
尽管如此,这对大多数人来说可能没什么用处。在大多数情况下,如果你正在做这样的事情,你可能需要重新考虑你的设计,但在某些情况下你别无选择。