您好我有两张桌子 INVOICE 和 CUSTOMER 在 INVOICE 表格中,当我创建发票视图时,我需要参考 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
这种子查询可能吗?
答案 0 :(得分:2)
执行此操作的正确方法是使用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;
答案 1 :(得分:2)
回应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
进行相同的查询花了9毫秒。看看那些读物!订单表的15000和Customers表的80000。使用JOIN
意味着它们分别为3000和40。
所以,我必须再次问,"为什么你不想使用JOIN
?"没有充分的理由这样做。即使没有Keys和索引,性能也会呈指数级增长。诚实地说,你所做的是一个可怕的错误。请,请重新考虑使用子查询。