2017-12-17 13 views
0

안녕을 여러 필드를 선택하는 방법은 내가 고객 테이블의 참조가있는 INVOICE 테이블에 두 테이블 INVOICE고객 (를 고객 ID) 내가 필요가 나는 송장보기가 하나 개의 동일한 하위 쿼리에T-SQL : 하위 쿼리

NB를 NAME이메일 및 기타 필드를 가져 오지 만들 때 : 나는 CA NNOT 사용은 내가 지금하고 내가

SELECT 
InvoiceId, 
(SELECT FullName, Email, .... FROM Customer WHERE CustomerId = CustomerId) AS CustomerFullName, CustomerEmail, .... 
FROM 
InVoice 

가능한 서브 쿼리의 종류입니다 무엇이 필요

SELECT 
InvoiceId, 
(SELECT FullName FROM Customer WHERE CustomerId = CustomerId) AS CustomerFullName, 
(SELECT Email FROM Customer WHERE CustomerId = CustomerId) AS CustomerEmail 
... 
FROM 
InVoice 

무엇

가입?

+1

"** * NB : 나는 사용할 수 없습니다. ** **"물어보십시오. 왜? 별도로, 아니요, 하위 쿼리 (여러 행 또는 여러 열)에서 여러 값을 반환 할 수 없습니다. 그들은 단일 값을 리턴해야합니다. 'JOIN'을 사용하는 것이 여기에 대한 대답입니다. 내가 왜 당신을 사용하고 싶은지 아무 이유없이 생각할 수 없으며, 모든 ** 열에 하위 쿼리를 사용하면 끔찍한 성능이 나빠질 것입니다. 테이블은 각 열의 값에 대해 (적어도) 스캔해야합니다. – Larnu

+0

옳은 일은 그것을 사용하고 싶지 않다는 것입니다. 나는 첫 번째 스타일로 지난 10 년 동안 많은 SQL 쿼리 작성을 리팩터링하려고합니다. 그리고 나는이 쿼리를 리팩토링하는 쉬운 방법을 찾는다. JOIN을 쓰지 않아도된다. 크로스, 인터 널, 내부 ...를 사용할 때 모든 외래 키를 검사 할 필요가있다. JOIN –

+0

@JeanClaudeADIBA 작동한다면 변경하지 마라. . 나는 비추천 암시 적 조인을 좋아하지 않지만, 내가 그것을 발견 할 때 나는 엄격한 필요가없는 한 그것을 망치 려하지 않는다. C#, Delphi, VB, Java 등을 프로그래밍 할 수 있다면 semi-auto sql rewriter를 쉽게 만들 수 있습니다. 물론 동일한 스타일로 작성된 모든 수동 작업을 더 많이 수행해야합니다. – jean

답변

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; 
+0

"j" 키보드의 키보드가 깨져서 개인적으로 다음 중 하나를 제안합니다. * 1. 새 키보드를 구입하십시오. 2. 'j'가있는 페이지를 찾아 복사 한 다음 쿼리 디자이너에 붙여 넣으십시오. 3. 화면 키보드를 사용하십시오. * 왜 OP가 여기서 'JOIN'을 사용할 수 없는지에 대한 "좋은"이유를 생각할 수 없습니다. – Larnu

+0

조언 해 주셔서 감사합니다. @ 라루 누 (Larnu)는 성능 문제가 있다고 말했다. 그리고 나는 모든 리팩토링을합니다 (DBA가 아닙니다). 사실 나는 메인 테이블 (인보이스)의 모든 행에서 쿼리 결과에 customerid가 OUTER APPLY와 JOIN 중 하나가 null 인 것을 확인하여 최상의 성능을 제공합니다. –

+1

@ JeanClaudeADIBA 다시 왜 JOIN을 사용하지 않을 수 있습니까? 에스? 성능 문제는 쿼리에'JOIN' 구문이 존재하기 때문에 발생하는 것이 아니라 테이블/쿼리, 인덱싱 불량, 서버 구성 또는 SQL (언어) 사용 빈도가 근본적인 설계 문제로 인해 발생할 수 있습니다. – alroc

2

오른쪽 사물의 영업 이익의 진술에 대응하기 위해 내가 안입니다 그것을 사용하고 싶다.

JOIN을 사용하지 않는 것일까? 예를 들어 ... 아주 글자 그대로 끔찍한 생각 서브 쿼리이다 사용의 마이크로 소프트에서 WideWorldImporters DATBASE에 아주 간단한 쿼리를 보자 :

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가 걸렸습니다. 그리고 그 읽기를보세요!Orders 테이블의 15000 및 Customers 테이블의 80000 JOIN을 사용하면 각각 3000과 40에 해당합니다.

그래서 다시 묻습니다. "왜 JOIN을 사용하고 싶지 않으십니까?" 그렇게 할 이유가 없습니다. Keys와 인덱스가 없어도 성능은 기하 급수적으로 향상됩니다. 정직하게 당신이하는 일은 끔찍한 실수입니다. 하위 쿼리 사용에 대해 다시 생각해주십시오.

+0

조언을 주셔서 감사합니다. 고려해 보겠습니다.) –