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

时间:2017-12-17 11:47:15

标签: sql sql-server tsql

您好我有两张桌子 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 

这种子查询可能吗?

2 个答案:

答案 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和索引,性能也会呈指数级增长。诚实地说,你所做的是一个可怕的错误。请,请重新考虑使用子查询。