嗨我在INVOICE表中有两个表INVOICE和CUSTOMER我有一个CUSTOMER表(CustomerId)的引用,当我创建发票视图时,我需要在一个相同的子查询中检索NAME和EMAIL以及其他字段
注意:我不能使用加入
我现在在做什么
SELECT
InvoiceId,
(SELECT FullName FROM Customer WHERE CustomerId = CustomerId) AS CustomerFullName,
(SELECT Email FROM Customer WHERE CustomerId = CustomerId) AS CustomerEmail
...
FROM
InVoice
我需要的是
SELECT
InvoiceId,
(SELECT FullName, Email, .... FROM Customer WHERE CustomerId = CustomerId) AS CustomerFullName, CustomerEmail, ....
FROM
InVoice
这种子查询可能吗?
正确的方法是使用join
。例如,如果键盘上的“j”键坏了,您可以使用apply
表达:
SELECT i.InvoiceId, c.*
FROM InVoice i OUTER APPLY
(SELECT c.FullName, c.Email, . . .
FROM Customer c
WHERE c.CustomerId = i.CustomerId
) c;
回应OP的声明
正确的事情是我不想使用它。
你为什么不想使用JOIN
?从字面上看,使用子查询是一个糟糕的想法...例如,让我们对来自Microsoft的WideWorldImporters数据库进行非常简单的查询:
SELECT I.InvoiceID,
O.OrderID,
O.OrderDate, O.ExpectedDeliveryDate
FROM sales.Invoices I
JOIN sales.Orders O ON I.OrderID = O.OrderID
WHERE I.InvoiceID BETWEEN 1 AND 1000;
启用统计时间和IO,会导致:
Table 'Orders'. Scan count 0, logical reads 3000, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Invoices'. Scan count 1, logical reads 182, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 4 ms, elapsed time = 4 ms.
那时候即将到来。现在,让我们使用您的方法(使用子查询):
SELECT I.InvoiceID,
(SELECT O.OrderID FROM sales.Orders O WHERE I.OrderID = O.OrderID) AS OrderID,
(SELECT O.OrderDate FROM sales.Orders O WHERE I.OrderID = O.OrderID) AS OrderDate,
(SELECT O.ExpectedDeliveryDate FROM sales.Orders O WHERE I.OrderID = O.OrderID) AS ExpectedDeliveryDate
FROM sales.Invoices I
WHERE I.InvoiceID BETWEEN 1 AND 1000;
和成本?
Table 'Orders'. Scan count 0, logical reads 9000, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Invoices'. Scan count 1, logical reads 182, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 10 ms, elapsed time = 10 ms.
嗯,毫不奇怪,读数翻了三倍,从3000到9000!此外,执行时间超过两倍。仅仅因为我们为每列使用了子查询。
现在,为了证明更进一步的观点,让我们来看看客户表,看看这是多么“糟糕”:
PRINT 'Using JOIN';
SELECT I.InvoiceID,
C.CustomerName,
C.DeliveryPostalCode,
O.OrderID,
O.OrderDate, O.ExpectedDeliveryDate
FROM sales.Invoices I
JOIN sales.Orders O ON I.OrderID = O.OrderID
JOIN sales.Customers C ON O.CustomerID = C.CustomerID
WHERE I.InvoiceID BETWEEN 1 AND 1000;
PRINT 'Using Subqueries'
SELECT I.InvoiceID,
(SELECT C.Customername FROM sales.Customers C WHERE C.CustomerID = (SELECT O.CustomerID FROM sales.Orders O WHERE I.OrderID = O.OrderID)) AS CustomerName,
(SELECT C.DeliveryPostalCode FROM sales.Customers C WHERE C.CustomerID = (SELECT O.CustomerID FROM sales.Orders O WHERE I.OrderID = O.OrderID)) AS DeliveryPostalCode,
(SELECT O.OrderID FROM sales.Orders O WHERE I.OrderID = O.OrderID) AS OrderID,
(SELECT O.OrderDate FROM sales.Orders O WHERE I.OrderID = O.OrderID) AS OrderDate,
(SELECT O.ExpectedDeliveryDate FROM sales.Orders O WHERE I.OrderID = O.OrderID) AS ExpectedDeliveryDate
FROM sales.Invoices I
WHERE I.InvoiceID BETWEEN 1 AND 1000;
结果?
Using JOIN
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 0 ms.
(1000 rows affected)
Table 'Workfile'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Customers'. Scan count 1, logical reads 40, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Orders'. Scan count 0, logical reads 3000, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Invoices'. Scan count 1, logical reads 182, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 9 ms, elapsed time = 8 ms.
Using Subqueries
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 0 ms.
(1000 rows affected)
Table 'Orders'. Scan count 0, logical reads 15000, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Customers'. Scan count 2000, logical reads 80000, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Invoices'. Scan count 1, logical reads 182, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 2028 ms, elapsed time = 2029 ms.
看看那个执行时间!超过2秒!使用JOIN
进行相同的查询花了9ms。看看那些读物!订单表的15000和Customers表的80000。使用JOIN
意味着它们分别为3000和40。
所以,我不得不再次问:“为什么你不想使用JOIN
?”没有充分的理由这样做。即使没有Keys和索引,性能也会呈指数级增长。诚实地说,你所做的是一个可怕的错误。请,请重新考虑使用子查询。