[SQL] 내가 교차 사용에 적용해야 할 때 내부 조인?
SQL내가 교차 사용에 적용해야 할 때 내부 조인?
CROSS APPLY가 사용하는 주요 목적은 무엇인가?
나는 (왠지, 인터넷 게시물을 통해) 크로스 당신이 분할하는 경우 대용량 데이터 세트를 통해 선정 할 때보다 효율적으로 할 수있다 적용 할 것을 읽었습니다. (페이징 마음에 온다)
또한 CROSS 오른쪽 테이블로 UDF를 필요로하지 않는다 적용 것을 알고있다.
대부분의 INNER 쿼리를 (한 - 투 - 많은 관계), I는 CROSS APPLY를 사용하도록 다시 작성할 수 있지만, 그들은 항상 나에게 해당하는 실행 계획을 제공 가입하세요.
사람이 나에게 CROSS은 INNER뿐만 아니라 작동 가입하는 경우에 차이가 적용 할 때의 좋은 예를 주실 수 있습니까?
편집하다:
실행 계획은 정확히 같은 곳 여기에 사소한 예제입니다. (나에게 그들이 다른 하나를 보여주고 크로스가 적용되는 경우는 빠른 / 더 효율적입니다)
create table Company (
companyId int identity(1,1)
, companyName varchar(100)
, zipcode varchar(10)
, constraint PK_Company primary key (companyId)
)
GO
create table Person (
personId int identity(1,1)
, personName varchar(100)
, companyId int
, constraint FK_Person_CompanyId foreign key (companyId) references dbo.Company(companyId)
, constraint PK_Person primary key (personId)
)
GO
insert Company
select 'ABC Company', '19808' union
select 'XYZ Company', '08534' union
select '123 Company', '10016'
insert Person
select 'Alan', 1 union
select 'Bobby', 1 union
select 'Chris', 1 union
select 'Xavier', 2 union
select 'Yoshi', 2 union
select 'Zambrano', 2 union
select 'Player 1', 3 union
select 'Player 2', 3 union
select 'Player 3', 3
/* using CROSS APPLY */
select *
from Person p
cross apply (
select *
from Company c
where p.companyid = c.companyId
) Czip
/* the equivalent query using INNER JOIN */
select *
from Person p
inner join Company c on p.companyid = c.companyId
해결법
-
==============================
1.자세한 성능 비교를 위해 내 블로그에있는 문서를 참조하십시오 :
자세한 성능 비교를 위해 내 블로그에있는 문서를 참조하십시오 :
CROSS 더 간단한이없는 일에 작품을 적용 조건을 가입하세요.
T1에서 T2 각 레코드에서 하나를 선택 3이 개 마지막 기록 :
SELECT t1.*, t2o.* FROM t1 CROSS APPLY ( SELECT TOP 3 * FROM t2 WHERE t2.t1_id = t1.id ORDER BY t2.rank DESC ) t2o
그것은 쉽게 INNER 배합 할 수없는 조건은 가입.
당신은 아마 사용 CTE의 창 기능과 같이 할 수 있습니다 :
WITH t2o AS ( SELECT t2.*, ROW_NUMBER() OVER (PARTITION BY t1_id ORDER BY rank) AS rn FROM t2 ) SELECT t1.*, t2o.* FROM t1 INNER JOIN t2o ON t2o.t1_id = t1.id AND t2o.rn <= 3
하지만이 덜 읽을 수 아마도 덜 효율적이다.
최신 정보:
그냥 체크.
마스터는 ID에 PRIMARY KEY와 20,000,000에 대한 기록의 테이블입니다.
이 쿼리 :
WITH q AS ( SELECT *, ROW_NUMBER() OVER (ORDER BY id) AS rn FROM master ), t AS ( SELECT 1 AS id UNION ALL SELECT 2 ) SELECT * FROM t JOIN q ON q.rn <= t.id
이 한 동안, 약 30 초 동안 실행 :
WITH t AS ( SELECT 1 AS id UNION ALL SELECT 2 ) SELECT * FROM t CROSS APPLY ( SELECT TOP (t.id) m.* FROM master m ORDER BY id ) q
인스턴트입니다.
-
==============================
2.십자가는 때때로 당신이 내부 조인과 함께 할 수없는 일을 할 수 있습니다 적용됩니다.
십자가는 때때로 당신이 내부 조인과 함께 할 수없는 일을 할 수 있습니다 적용됩니다.
실시 예 (구문 오류)
select F.* from sys.objects O inner join dbo.myTableFun(O.name) F on F.schema_id= O.schema_id
이는 구문 오류이며, 내부에 사용되는 경우에 참여하기 때문에, 테이블의 기능은 매개 변수 또는 상수 등을 취할 수있다. (즉, 테이블 함수 파라미터는 다른 테이블 칼럼에 의존 할 수 없다.)
하나:
select F.* from sys.objects O cross apply ( select * from dbo.myTableFun(O.name) ) F where F.schema_id= O.schema_id
이 법률이다.
편집하다: 또는 대안 적으로, 짧은 구문 (ErikE에 의해)
select F.* from sys.objects O cross apply dbo.myTableFun(O.name) F where F.schema_id= O.schema_id
편집하다:
노트 : 12.10 XC2 + 갖는 측면을 파생 테이블과 PostgreSQL 인포믹스 (9.3+)는 유사한 효과를 사용할 수있는 측면 부질있다.
-
==============================
3.당신이 두 개의 테이블을 고려하십시오.
당신이 두 개의 테이블을 고려하십시오.
마스터 테이블
x------x--------------------x | Id | Name | x------x--------------------x | 1 | A | | 2 | B | | 3 | C | x------x--------------------x
세부 사항 표
x------x--------------------x-------x | Id | PERIOD | QTY | x------x--------------------x-------x | 1 | 2014-01-13 | 10 | | 1 | 2014-01-11 | 15 | | 1 | 2014-01-12 | 20 | | 2 | 2014-01-06 | 30 | | 2 | 2014-01-08 | 40 | x------x--------------------x-------x
우리가 적용 CROSS으로 가입 INNER를 교체해야 할 여러 상황이 있습니다.
TOP N 결과에 따라 두 개의 테이블을 조인 (1)
우리는 정보 테이블에서 각 ID에 대한 마스터와 마지막 두 날짜에서 ID와 이름을 선택해야하는 경우 고려하십시오.
SELECT M.ID,M.NAME,D.PERIOD,D.QTY FROM MASTER M INNER JOIN ( SELECT TOP 2 ID, PERIOD,QTY FROM DETAILS D ORDER BY CAST(PERIOD AS DATE)DESC )D ON M.ID=D.ID
위의 쿼리는 다음과 같은 결과를 생성합니다.
x------x---------x--------------x-------x | Id | Name | PERIOD | QTY | x------x---------x--------------x-------x | 1 | A | 2014-01-13 | 10 | | 1 | A | 2014-01-12 | 20 | x------x---------x--------------x-------x
그것은 지난 날짜의 ID와 마지막 두 날짜에 대한 결과를 생성 만 잘못된 ID를 외부 쿼리에이 기록에 합류 참조하십시오. 이 두 ID가 1과 2를 반환해야하지만, 한 지난 2 날짜가 1 개만 있기 때문에 돌려 보냈다. 이를 위해, 우리는 CROSS가 적용 사용해야합니다.
SELECT M.ID,M.NAME,D.PERIOD,D.QTY FROM MASTER M CROSS APPLY ( SELECT TOP 2 ID, PERIOD,QTY FROM DETAILS D WHERE M.ID=D.ID ORDER BY CAST(PERIOD AS DATE)DESC )D
그리고 다음과 같은 결과를 형성한다.
x------x---------x--------------x-------x | Id | Name | PERIOD | QTY | x------x---------x--------------x-------x | 1 | A | 2014-01-13 | 10 | | 1 | A | 2014-01-12 | 20 | | 2 | B | 2014-01-08 | 40 | | 2 | B | 2014-01-06 | 30 | x------x---------x--------------x-------x
그것이 작동 방법은 다음과 같습니다. CROSS 내부 쿼리 INNER (이것은 컴파일 오류가 발생합니다)이 작업을 수행 할 수없는 외부 조인 테이블을 참조 할 수 있습니다 적용됩니다. 마지막 두 날짜를 발견하면, 가입은 즉, WHERE M.ID = D.ID을 적용 CROSS 내부에서 수행된다.
2. 우리는 INNER이 기능을 사용하여 기능을 가입이 필요합니다.
우리는 마스터 테이블과 함수의 결과를 얻을 필요가있을 때 INNER와 교체 가입으로 CROSS 사용할 수 있습니다 적용됩니다.
SELECT M.ID,M.NAME,C.PERIOD,C.QTY FROM MASTER M CROSS APPLY dbo.FnGetQty(M.ID) C
그리고 여기에 기능입니다
CREATE FUNCTION FnGetQty ( @Id INT ) RETURNS TABLE AS RETURN ( SELECT ID,PERIOD,QTY FROM DETAILS WHERE ID=@Id )
이는 다음과 같은 결과를 생성
x------x---------x--------------x-------x | Id | Name | PERIOD | QTY | x------x---------x--------------x-------x | 1 | A | 2014-01-13 | 10 | | 1 | A | 2014-01-11 | 15 | | 1 | A | 2014-01-12 | 20 | | 2 | B | 2014-01-06 | 30 | | 2 | B | 2014-01-08 | 40 | x------x---------x--------------x-------x
십자가의 또 다른 장점은 적용
UNPIVOT를 대체 사용할 수 있습니다 적용됩니다. 어느 CROSS 적용 또는 OUTER은 교환 할 수있는, 여기에 사용할 수 있습니다 적용됩니다.
당신은 아래 표 (이름 MYTABLE)가 고려하십시오.
x------x-------------x--------------x | Id | FROMDATE | TODATE | x------x-------------x--------------x | 1 | 2014-01-11 | 2014-01-13 | | 1 | 2014-02-23 | 2014-02-27 | | 2 | 2014-05-06 | 2014-05-30 | | 3 | NULL | NULL | x------x-------------x--------------x
쿼리는 다음과 같습니다.
SELECT DISTINCT ID,DATES FROM MYTABLE CROSS APPLY(VALUES (FROMDATE),(TODATE)) COLUMNNAMES(DATES)
이는 당신에게 결과를 제공합니다
x------x-------------x | Id | DATES | x------x-------------x | 1 | 2014-01-11 | | 1 | 2014-01-13 | | 1 | 2014-02-23 | | 1 | 2014-02-27 | | 2 | 2014-05-06 | | 2 | 2014-05-30 | | 3 | NULL | x------x-------------x
-
==============================
4.CROSS 복잡한 / 중첩 된 쿼리에서 계산 된 필드로 작업 할 때 일정한 간격을 채울 수 적용, 그들을 간단하고 쉽게 읽을 수 있도록 나에게 보인다.
CROSS 복잡한 / 중첩 된 쿼리에서 계산 된 필드로 작업 할 때 일정한 간격을 채울 수 적용, 그들을 간단하고 쉽게 읽을 수 있도록 나에게 보인다.
간단한 예 : 당신은 DOB가 있고 당신은 당신의 최종 사용자 응용 프로그램에서 사용하는 등 나이, 연령 집단, AgeAtHiring, MinimumRetirementDate 같은도 (고용으로) 다른 데이터 소스에 의존 현재 여러 연령 관련 분야, 원하는 (엑셀 피벗 테이블, 예를 들면).
옵션 제한 거의 우아한 있습니다 :
내가 뭐 놓친 거 없니? 아마, 그래서 의견을 주시기 바랍니다. 하지만, 이봐, CROSS는 적용 이러한 상황에서 신의 선물 같다 : 당신은 그냥 crossTbl 봐라로 (someFormula로 선택 tbl.value + 1) CROSS이 적용 단순한를 추가! 새 필드는 이제 항상 원본 데이터에 거기에 있었다 거의 같은를 사용할 수 있습니다.
CROSS를 통해 유입 값은 캔을 적용 ...
젠장, 그들이 할 수 없어 아무것도 없다!
-
==============================
5.크로스는 잘 작동과 XML 필드뿐만 아니라 적용됩니다. 당신은 다른 분야와 함께 노드 값을 선택하고자하는 경우.
크로스는 잘 작동과 XML 필드뿐만 아니라 적용됩니다. 당신은 다른 분야와 함께 노드 값을 선택하고자하는 경우.
예를 들어, 일부 XML을 포함하는 테이블이있는 경우
쿼리를 사용하여
SELECT id as [xt_id] ,xmlfield.value('(/root/@attribute)[1]', 'varchar(50)') root_attribute_value ,node_attribute_value = [some_node].value('@value', 'int') ,lt.lt_name FROM dbo.table_with_xml xt CROSS APPLY xmlfield.nodes('/root/subnode1/some_node') as g ([some_node]) LEFT OUTER JOIN dbo.lookup_table lt ON [some_node].value('@value', 'int') = lt.lt_id
결과를 반환합니다
xt_id root_attribute_value node_attribute_value lt_name ---------------------------------------------------------------------- 1 test1 1 Benefits 1 test1 4 FINRPTCOMPANY
-
==============================
6.이것은 이미 잘 기술적으로 대답하지만, 내가 그것을 매우 유용한 방법의 구체적인 예를 제공 할 수있다 :
이것은 이미 잘 기술적으로 대답하지만, 내가 그것을 매우 유용한 방법의 구체적인 예를 제공 할 수있다 :
두 테이블, 고객 및 주문을 말할 수 있습니다. 고객이 많은 주문이있다.
나는 나 고객에 대한 세부 사항 제공하는보기, 그들은이 만든 가장 최근의 순서를 만들려고합니다. 단지 조인, 이것은 꽤 아닌 일부 자기 조인과 통합을 필요로한다. 그러나 십자가에 쉽게 수퍼 적용 :
SELECT * FROM Customer CROSS APPLY ( SELECT TOP 1 * FROM Order WHERE Order.CustomerId = Customer.CustomerId ORDER BY OrderDate DESC ) T
-
==============================
7.당신은 하위 쿼리의 열을 필요로하는 곳에 크로스는 서브 쿼리의를 대체 할 수 적용
당신은 하위 쿼리의 열을 필요로하는 곳에 크로스는 서브 쿼리의를 대체 할 수 적용
하위 쿼리
select * from person p where p.companyId in(select c.companyId from company c where c.companyname like '%yyy%')
여기에 내가 회사 테이블의 열을 선택할 수 없습니다 그래서 사용하여 크로스 적용
select P.*,T.CompanyName from Person p cross apply ( select * from Company C where p.companyid = c.companyId and c.CompanyName like '%yyy%' ) T
-
==============================
8.나는 그것을 읽을 수 있어야한다 생각)
나는 그것을 읽을 수 있어야한다 생각)
CROSS는 UDF가 왼쪽에있는 테이블에서 각 행에 적용되는 사용되고 있음을 그들에게 읽는 사람들을 위해 다소 독특한 것입니다 적용됩니다.
당연히, 크로스 더 나은 다른 친구가 이상 게시하는 가입하기보다 사용되는 적용되는 다른 제한 사항이 있습니다.
-
==============================
9.여기에 자신의 성능 차이 이상 조인을 사용하여, 모두를 설명하는 문서입니다.
여기에 자신의 성능 차이 이상 조인을 사용하여, 모두를 설명하는 문서입니다.
SQL 서버 CROSS APPLY와 OUTER은 이상 JOINS 적용
이 문서에서 제안한 것처럼, 정상적인 조작 (INNER AND CROSS)에 가입하기에 사이에 성능 차이가 없다.
이 같은 쿼리를해야 할 때 사용 차이는 도착 :
CREATE FUNCTION dbo.fn_GetAllEmployeeOfADepartment(@DeptID AS INT) RETURNS TABLE AS RETURN ( SELECT * FROM Employee E WHERE E.DepartmentID = @DeptID ) GO SELECT * FROM Department D CROSS APPLY dbo.fn_GetAllEmployeeOfADepartment(D.DepartmentID)
당신이 기능과 관련된해야 할 때이다. 이 INNER는 당신에게 오류 "다중 부분 식별자"D.DepartmentID 줄 것이다, 가입 사용하여 수행 할 수 없습니다 "구속되지 않을 수 있습니다." 각 행 읽을 때 다음의 값은 함수로 전달된다. 사운드 나 냉각. :)
-
==============================
10.그럼 내가하지 않도록 내부 조인 사용하여 equalivent 방법이 있다면 이유 등이 자격을 크로스가 내부 조인 대 적용을 사용하려면,하지만 확실하지 않다, 그래서이 쿼리, 크로스 적용을 사용하여 포럼 포스트 나에게 대답 한 경우 :
그럼 내가하지 않도록 내부 조인 사용하여 equalivent 방법이 있다면 이유 등이 자격을 크로스가 내부 조인 대 적용을 사용하려면,하지만 확실하지 않다, 그래서이 쿼리, 크로스 적용을 사용하여 포럼 포스트 나에게 대답 한 경우 :
Create PROCEDURE [dbo].[Message_FindHighestMatches] -- Declare the Topical Neighborhood @TopicalNeighborhood nchar(255)
같이 BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from -- interfering with SELECT statements. SET NOCOUNT ON Create table #temp ( MessageID int, Subjects nchar(255), SubjectsCount int ) Insert into #temp Select MessageID, Subjects, SubjectsCount From Message Select Top 20 MessageID, Subjects, SubjectsCount, (t.cnt * 100)/t3.inputvalues as MatchPercentage From #temp cross apply (select count(*) as cnt from dbo.Split(Subjects,',') as t1 join dbo.Split(@TopicalNeighborhood,',') as t2 on t1.value = t2.value) as t cross apply (select count(*) as inputValues from dbo.Split(@TopicalNeighborhood,',')) as t3 Order By MatchPercentage desc drop table #temp
종료
-
==============================
11.의 본질은 운영자가 FROM 절에서 연산자의 왼쪽과 오른쪽 사이의 상관 관계를 허용하는 것입니다 적용됩니다.
의 본질은 운영자가 FROM 절에서 연산자의 왼쪽과 오른쪽 사이의 상관 관계를 허용하는 것입니다 적용됩니다.
가입 대조적으로, 입력들 간의 상관 관계를 허용하지 않는다.
연산자를 적용의 상관 관계에 대해 말하기, 우리가 넣을 수 있습니다 오른쪽에 의미 :
둘은 여러 열과 행을 반환 할 수 있습니다.
-
==============================
12.이것은 아마도 오래된 질문이지만, 난 여전히 CROSS의 힘 로직의 재사용을 단순화하기 위해 적용 및 결과에 대해 "체인"메커니즘을 제공하기 위해 사랑 해요.
이것은 아마도 오래된 질문이지만, 난 여전히 CROSS의 힘 로직의 재사용을 단순화하기 위해 적용 및 결과에 대해 "체인"메커니즘을 제공하기 위해 사랑 해요.
나는 당신이 CROSS이 모든 혼란에서 얻는 일없이 데이터 세트에 복잡한 논리 연산을 수행하는 데 적용 사용하는 방법의 간단한 예를 보여주는 아래에 SQL 바이올린을 제공했습니다. 그것은 여기에 더 복잡한 계산에서 추정하기 어렵지 않다.
http://sqlfiddle.com/#!3/23862/2
-
==============================
13.고용 CROSS이 적용 대부분의 질의는 INNER를 사용하여 다시 가입 할 수 있지만, CROSS은이 (가) 발생에 가입하기 전에 세트 아직 결합되는 제한 할 수 있기 때문에, 더 나은 실행 계획 및 더 나은 성능을 얻을 수 적용.
고용 CROSS이 적용 대부분의 질의는 INNER를 사용하여 다시 가입 할 수 있지만, CROSS은이 (가) 발생에 가입하기 전에 세트 아직 결합되는 제한 할 수 있기 때문에, 더 나은 실행 계획 및 더 나은 성능을 얻을 수 적용.
여기에서 도난
from https://stackoverflow.com/questions/1139160/when-should-i-use-cross-apply-over-inner-join by cc-by-sa and MIT license
'SQL' 카테고리의 다른 글
[SQL] 어떻게 PostgreSQL을에 삽입 성능을 향상하기 (0) | 2020.03.11 |
---|---|
[SQL] 어떻게 MySQL 데이터베이스 / 테이블 / 열이 설정 어떤 문자 볼 수 있습니까? (0) | 2020.03.11 |
[SQL] 어떻게 된 PreparedStatement 피하거나 방지 SQL 주입을합니까? (0) | 2020.03.11 |
[SQL] 각 범주에 대한 상위 10 개의 레코드를 선택 (0) | 2020.03.11 |
[SQL] 어떻게 SQL 데이터베이스 테이블에서 n 번째 행을 선택하려면? (0) | 2020.03.11 |