T-SQL:如何在SubQuery中选择多个字段

问题描述 投票:0回答:2

嗨我在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 

这种子查询可能吗?

sql sql-server tsql
2个回答
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;

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进行相同的查询花了9ms。看看那些读物!订单表的15000和Customers表的80000。使用JOIN意味着它们分别为3000和40。

所以,我不得不再次问:“为什么你不想使用JOIN?”没有充分的理由这样做。即使没有Keys和索引,性能也会呈指数级增长。诚实地说,你所做的是一个可怕的错误。请,请重新考虑使用子查询。

© www.soinside.com 2019 - 2024. All rights reserved.