복붙노트

[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. ==============================

    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. ==============================

    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. ==============================

    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. ==============================

    4.CROSS 복잡한 / 중첩 된 쿼리에서 계산 된 필드로 작업 할 때 일정한 간격을 채울 수 적용, 그들을 간단하고 쉽게 읽을 수 있도록 나에게 보인다.

    CROSS 복잡한 / 중첩 된 쿼리에서 계산 된 필드로 작업 할 때 일정한 간격을 채울 수 적용, 그들을 간단하고 쉽게 읽을 수 있도록 나에게 보인다.

    간단한 예 : 당신은 DOB가 있고 당신은 당신의 최종 사용자 응용 프로그램에서 사용하는 등 나이, 연령 집단, AgeAtHiring, MinimumRetirementDate 같은도 (고용으로) 다른 데이터 소스에 의존 현재 여러 연령 관련 분야, 원하는 (엑셀 피벗 테이블, 예를 들면).

    옵션 제한 거의 우아한 있습니다 :

    내가 뭐 놓친 거 없니? 아마, 그래서 의견을 주시기 바랍니다. 하지만, 이봐, CROSS는 적용 이러한 상황에서 신의 선물 같다 : 당신은 그냥 crossTbl 봐라로 (someFormula로 선택 tbl.value + 1) CROSS이 적용 단순한를 추가! 새 필드는 이제 항상 원본 데이터에 거기에 있었다 거의 같은를 사용할 수 있습니다.

    CROSS를 통해 유입 값은 캔을 적용 ...

    젠장, 그들이 할 수 없어 아무것도 없다!

  5. ==============================

    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. ==============================

    6.이것은 이미 잘 기술적으로 대답하지만, 내가 그것을 매우 유용한 방법의 구체적인 예를 제공 할 수있다 :

    이것은 이미 잘 기술적으로 대답하지만, 내가 그것을 매우 유용한 방법의 구체적인 예를 제공 할 수있다 :

    두 테이블, 고객 및 주문을 말할 수 있습니다. 고객이 많은 주문이있다.

    나는 나 고객에 대한 세부 사항 제공하는보기, 그들은이 만든 가장 최근의 순서를 만들려고합니다. 단지 조인, 이것은 꽤 아닌 일부 자기 조인과 통합을 필요로한다. 그러나 십자가에 쉽게 수퍼 적용 :

    SELECT *
    FROM Customer
    CROSS APPLY (
      SELECT TOP 1 *
      FROM Order
      WHERE Order.CustomerId = Customer.CustomerId
      ORDER BY OrderDate DESC
    ) T
    
  7. ==============================

    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. ==============================

    8.나는 그것을 읽을 수 있어야한다 생각)

    나는 그것을 읽을 수 있어야한다 생각)

    CROSS는 UDF가 왼쪽에있는 테이블에서 각 행에 적용되는 사용되고 있음을 그들에게 읽는 사람들을 위해 다소 독특한 것입니다 적용됩니다.

    당연히, 크로스 더 나은 다른 친구가 이상 게시하는 가입하기보다 사용되는 적용되는 다른 제한 사항이 있습니다.

  9. ==============================

    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. ==============================

    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. ==============================

    11.의 본질은 운영자가 FROM 절에서 연산자의 왼쪽과 오른쪽 사이의 상관 관계를 허용하는 것입니다 적용됩니다.

    의 본질은 운영자가 FROM 절에서 연산자의 왼쪽과 오른쪽 사이의 상관 관계를 허용하는 것입니다 적용됩니다.

    가입 대조적으로, 입력들 간의 상관 관계를 허용하지 않는다.

    연산자를 적용의 상관 관계에 대해 말하기, 우리가 넣을 수 있습니다 오른쪽에 의미 :

    둘은 여러 열과 행을 반환 할 수 있습니다.

  12. ==============================

    12.이것은 아마도 오래된 질문이지만, 난 여전히 CROSS의 힘 로직의 재사용을 단순화하기 위해 적용 및 결과에 대해 "체인"메커니즘을 제공하기 위해 사랑 해요.

    이것은 아마도 오래된 질문이지만, 난 여전히 CROSS의 힘 로직의 재사용을 단순화하기 위해 적용 및 결과에 대해 "체인"메커니즘을 제공하기 위해 사랑 해요.

    나는 당신이 CROSS이 모든 혼란에서 얻는 일없이 데이터 세트에 복잡한 논리 연산을 수행하는 데 적용 사용하는 방법의 간단한 예를 보여주는 아래에 SQL 바이올린을 제공했습니다. 그것은 여기에 더 복잡한 계산에서 추정하기 어렵지 않다.

    http://sqlfiddle.com/#!3/23862/2

  13. ==============================

    13.고용 CROSS이 적용 대부분의 질의는 INNER를 사용하여 다시 가입 할 수 있지만, CROSS은이 (가) 발생에 가입하기 전에 세트 아직 결합되는 제한 할 수 있기 때문에, 더 나은 실행 계획 및 더 나은 성능을 얻을 수 적용.

    고용 CROSS이 적용 대부분의 질의는 INNER를 사용하여 다시 가입 할 수 있지만, CROSS은이 (가) 발생에 가입하기 전에 세트 아직 결합되는 제한 할 수 있기 때문에, 더 나은 실행 계획 및 더 나은 성능을 얻을 수 적용.

    여기에서 도난

  14. from https://stackoverflow.com/questions/1139160/when-should-i-use-cross-apply-over-inner-join by cc-by-sa and MIT license