2017-02-07 9 views
1

우리는 매일 다양한 상품이 포함 된 다양한 상품을 보유하고 있습니다.고객에게 제품을 문의 하시겠습니까?

고객은 이메일 알림을 신청할 수 있습니다. 이들은 매일 저녁 대량 발송되며 고객은 원하는 제품과 일치하는 주문 목록을받습니다.

  • 계정 (pk_AccountID, EmailAddress를, 제목, 이름)
  • Accounts_Alerts (fk_AccountID, pk_AlertID, 종류, 최대 가격, 컬러)
  • 제품 (pk_ItemID :

    데이터베이스에있는 세 개의 관련 테이블이 있습니다 , 카테고리, 제목, 가격, 색상, 날짜 변경)

지난 24 시간 동안 추가 된 최신 10 가지 제품을 각각의 옵션과 일치시키는 가장 효율적인 방법은 무엇입니까? 고객이 선택 했습니까?

이것은 내가 지금까지 가지고있는 것으로 작동하지만 날짜 별 상위 10 개 제품 (최신 추가 제품) 만 선택하지는 않습니다. 고객에게 이메일로 살펴볼 30 개 이상의 제품을 보내고 싶지는 않습니다.

SELECT 
    a.pk_AccountID, 
    aa.pk_AlertID, 
    a.Title As Title, 
    a.Name As Name,  
    a.EmailAddress As EmailAddress, 
    p.pk_ItemID As ItemID, 
    p.Category As Category, 
    p.Title As Title, 
    p.Price As Price, 
    p.Colour As Colour 

    FROM dbo.Accounts_Alerts aa 
    INNER JOIN dbo.Accounts a ON aa.fk_AccountID=a.pk_AccountID 
    LEFT OUTER JOIN dbo.Products p ON 
    (aa.Category = p.Category OR aa.Category IS NULL) 
    AND (aa.Colour = p.Colour OR aa.Colour IS NULL)  
    AND (aa.MaxPrice >= p.Price OR aa.MaxPrice IS NULL) 
    AND getdate()-1 < p.DateModified 

    WHERE 
    a.EmailAddress is not null AND 
    a.pk_AccountID = @AccountIDVariable 
    ORDER BY aa.pk_AlertID 
+0

'top 10 '을 사용하여 10 개의 행을 얻을 수 있습니다. –

+0

사용자 당 상위 10 개 제품이 필요한 경우 쿼리에 row_number() 또는 rank()를 추가하고 사용자별로 분할하고 <= 10으로 제한 할 수 있습니다. SQL을 다른 select 내에서 래핑해야합니다. –

+0

윈도우 화 된 함수 [행 번호] (https://msdn.microsoft.com/en-us/library/ms186734.aspx?f=255&MSPPError=-2147217396)는이 작업에 적합합니다. by by partition을 사용하여 고객 당 10 개의 행을 반환합니다. [MCVE]를 추가하면 (http://meta.stackoverflow.com/questions/333952/why-should-i-provide-an-mcve-for-what-seems-to-me-to-bea-a- very-simple-sql-query) 누군가가 당신의 쿼리를 재 작성하는 것을 도와 줄 것이라고 확신한다. –

답변

2

이 처리하는 일반적인 방법은 윈도우 기능 및 SQL Server가 아주 잘 처리하는 인라인보기, 함께. 예를 들어

:

SELECT 
    pk_AccountID, 
    pk_AlertID, 
    Title, 
    Name,  
    EmailAddress, 
    ItemID, 
    Category, 
    Title, 
    Price, 
    Colour 
FROM (
    SELECT 
     a.pk_AccountID, 
     aa.pk_AlertID, 
     a.Title As Title, 
     a.Name As Name,  
     a.EmailAddress As EmailAddress, 
     p.pk_ItemID As ItemID, 
     p.Category As Category, 
     p.Title As Title, 
     p.Price As Price, 
     p.Colour As Colour, 
     ROW_NUMBER() over (
      partition by a.pk_AccountID, p.pk_ItemID 
      order by p.DateModified desc 
     ) as rseq 
    FROM dbo.Accounts_Alerts aa 
    INNER JOIN dbo.Accounts a ON aa.fk_AccountID=a.pk_AccountID 
    LEFT OUTER JOIN dbo.Products p ON 
     (aa.Category = p.Category OR aa.Category IS NULL) 
     AND (aa.Colour = p.Colour OR aa.Colour IS NULL)  
     AND (aa.MaxPrice >= p.Price OR aa.MaxPrice IS NULL) 
     AND getdate()-1 < p.DateModified 
    WHERE 
     a.EmailAddress is not null AND 
     a.pk_AccountID = @AccountIDVariable 
) as any_alias_will_do 
where rseq <= 10 
ORDER BY pk_AlertID 

을 주목 ROW_NUMBER() 기능 - 당신이와 "에 의해 주문" "에 의해 분할"당신이 있는지를 확인해야합니다 올바른 기준이 (내가 여기에 계정 ID 및 항목 ID를 선택, 하지만 다른 필드가 필요할 수도 있습니다). 이것이 어떻게 작동하는지 이해하는 데 도움이되는 내부 쿼리 만 실행 해보십시오.

이 기술은 매우 다재다능합니다. 이러한 기능을 더 자세히 읽어 보시기 바랍니다.

+0

친절한 도움에 감사드립니다. 불행히도 코드를 편집하여 필자가 필요로하는 필드를 더 추가하고 테스트 한 결과, 오랜 시간 (1 분 이상)이 소요되었으며 때때로 메모리 오류가 발생합니다. 지난 24 시간의 제품을 임시 테이블로 선택하고 각 경고에 대해 제품을 선택하는 것이 더 빠릅니까? – TVRV8S

+0

나는 임시 테이블과 함께 그것을 시험해 보았다. 4 분이 지나간 다음 메모리가 부족합니다. 그런 다음 제품 테이블을 직접 사용하여 롤백했는데 매번 메모리가 부족합니다. – TVRV8S

+0

@ TVRV8S 첫째, 나는 당신이 말하는 것을 믿으며 더 이상의 통찰력 없이는 그것을 풀 수는 없지만 몇 가지 제안을드립니다. 둘째,이 쿼리 스타일은 유비쿼터스이며 잘 지원되므로 느려지지 않아야합니다! 셋째, 문제를 일으키는 것을 최적화하려면 테이블에 정의 된 인덱스와 쿼리에 대한 실행 계획 *에 익숙해야합니다. 실행 계획은 무엇이 가장 많은 리소스를 사용하고 있는지 알려주고 해결책.물론,이 기술을 모두 무시할 수는 있지만 충분히 저장하여 사용하면됩니다. – SlimsGhost