2010-06-14 59 views
0

非常複雜的查詢一直試圖構建它幾天,並取得了更多的成功。核心SQL設計者的複雜選擇查詢問題

我使用的是SQL-SERVER 2005標準

我需要的是:從廣告活動 5 CampaignVariants而2有設置最大PPU號和3是隨機的。

接下來條件是CampaignDailyBudget和CampaignTotalBudget低於什麼是在運動設定(計算是通過CampaignVariants連接到廣告活動在訪問者表的點擊次數對哪些用戶點擊)

下一頁條件 CampaignLanguage,CampaignCategory CampaignRegion和CampaignCountry必須是我通過(languageID,categoryID,regionID和countryID)發送給此選擇的人。

接下來的條件是我發送到這個select語句的IP地址不會在當前Campaign的IP列表中(我刪除了24小時IP的非活動狀態)。

換句話說,它得到5個CampaignVariants爲進入該網站,當我從用戶PublisherRegionUID,IP,語言,國家及地區採取

view diagram

詳情

用戶i從Visitor獲取countryID,regionID,ipID,PublisherRegionUID和languageID。這是過濾器參數。雖然我首先需要得到Publisher要在其網站上顯示的內容,然後使用除瀏覽器區域ID以外的所有參數,通過訪問者的參數篩選剩餘的所有廣告系列。

所以它有兩個實際的價格。一個發佈商想要發佈的內容以及另一個訪問者可以查看的內容...

campaignDailyBudget和campaignTotalBudget是創建Campaign的用戶設置的值。這兩個比較(每個廣告系列的點擊次數)*(campaignPPU),而日期過濾器明顯用於過濾從今天中午12:00到晚上11:59的campaignDailyBudget。 campaignTotalBudget不受日期的原因很明顯的

演示存儲過濾過程

ALTER PROCEDURE dbo.CampaignsGetCampaignVariants4Visitor 
    @publisherSiteRegionUID uniqueidentifier, 
    @visitorIP varchar(15), 
    @browserID tinyint, 
    @countryID tinyint, 
    @osID tinyint, 
    @languageID tinyint, 
    @acceptsCookies bit 
AS 
BEGIN 
    SET NOCOUNT ON; 

    -- check if such @publisherRegionUID exists 
    if exists(select publisherSiteRegionID from PublisherSiteRegions where [email protected]) 
     begin 

      declare @publisherSiteRegionID int 
      select @publisherSiteRegionID = publisherSiteRegionID from PublisherSiteRegions where [email protected] 

      -- get CampaignVariants 
      -- ** choose 2 highest PPU and 3 random CampaignVariants from Campaigns list 
      -- where regionID,countryID,categoryID,languageID meets Publisher and Visitor requirements 
      -- and Campaign.campaignDailyBudget<(sum of Clicks in Visitors per this Campaign)*Campaign.PPU during this day 
      -- and Campaign.campaignTotalBudget<(sum of Clicks in Visitors per this Campaign)*Campaign.PPU 
      -- and @visitorID does not appear in Campaigns2IPs with this Campaign 

      -- insert visitor 
      insert into Visitors (ipAddress,browserID,countryID,languageID,OSID,acceptsCookies) 
      values (@visitorIP,@browserID,@countryID,@languageID,@OSID,@acceptsCookies) 

      declare @visitorID int 
      select @visitorID = IDENT_CURRENT('Visitors') 

      -- add IP to pool Campaigns ** adding ip to all Campaigns whose CampaignVariants were chosen 

      -- add PublisherRegion2Visitor relationship 
      insert into PublisherSiteRegions2Visitors values (@visitorID,@publisherSiteRegionID) 

      -- add CampaignVariant2Visitor relationship 


     end 



END 
GO 
+0

哪個版本的sql server – 2010-06-14 15:23:10

+7

你的問題不夠清楚。請至少提供您的表格說明。 – redben 2010-06-14 15:26:58

+5

表格定義,樣本數據和預期輸出將非常有用。當他們試圖描述它時,通常很難理解一個人正在尋找什麼,特別是如果他們使用的術語與其他人不熟悉的話。 – 2010-06-14 15:27:17

回答

3

我也做了一些關於您的斜向需求的假設。我會一邊說一邊解釋代碼。請注意,我當然沒有合理的方式來測試這個代碼是否存在拼寫錯誤或小的邏輯錯誤。

也許可以將它作爲一個單獨的ginormous查詢來編寫,但由於SQL優化器可能會在構建過大查詢計劃時遇到問題,所以這會非常尷尬,容易出現性能問題。一個選項是將它寫成一系列查詢,填充臨時表以供後續查詢使用(這樣可以更簡單地進行調試)。我選擇使用一系列CTE表格將其作爲一個大的公用表表達式語句來編寫,這很大程度上是因爲它的「流動性」更好,它可能比許多臨時表版本更好。

第一個假設:那裏有幾個ciruclar參考。 Campaign有鏈接到國家和地區的鏈接,所以必須檢查這兩個參數值 - 即使基於從Countries到Region的錶鏈接,這個過濾器可能簡化爲只檢查Country(假設國家參數值始終「在」區域參數中)。這同樣適用於語言和類別,也可能適用於IP和訪問者。這似乎是馬虎的設計;如果可以清除它,或者如果可以對數據的有效性進行假設,則可以簡化查詢。

第二個假設:參數以@Region,@Country等形式作爲變量傳遞。此外,只有一個IP地址被傳入;如果沒有,那麼你需要傳入多個值,設置一個包含這些值的臨時表,並將其添加爲使用@IP參數的過濾器。

所以,第1步是第一遍確定「合格」活動,通過拉掉所有那些共享所需的國家,地區,語言,cateogory,那有與之相關的一個IP地址:

WITH cteEligibleCampaigns (CampaignId) 
as (select CampaignId 
     from Campaigns2Regions 
     where RegionId = @RegionId 
    intersect select CampaignId 
     from Campaign2Countries 
     where CountryId = @CountryId 
    intersect select CampaignId 
     from Campaign2Languages 
     where LanguageId = @LanguageId 
    intersect select CampaignId 
     from Campaign2Categories 
     where CategoryId = @CategoryId 
    except select CampaignId 
     from Campaigns2IPs 
     where IPID = @IPId) 

下一步,從這些篩選出那些其中「CampaignDailyBudget和CampaignTotalBudget低於什麼是在運動設定(計算是通過在其上用戶點擊CampaignVariants連接到廣告活動在訪問者表的點擊的數目)」的項目。這個要求對我來說並不完全清楚。我選擇將其解釋爲「僅包含這些廣告系列,如果您計算這些廣告系列的CampaignVariants的訪問者人數,則總數將少於CampaignDailyBudget和CampaignTotalBudget」。請注意,這裏我介紹一個隨機值,稍後用於選擇隨機行。

,cteTargetCampaigns (CampaignId, RandomNumber) 
    as (select CampaignId, checksum(newid() RandomNumber) 
     from cteEligibleCampaigns ec 
     inner join Campaigns ca 
     on ca.CampgainId = ec.CampaignId 
     inner join CampaignVariants cv 
     on cv.CampgainId = ec.CampaignId 
     inner join CampaignVariants2Visitors cvv 
     on cvv.CampaignVariantId = cv. CampaignVariantId 
     group by ec.CampaignId 
     having count(*) < ca.CampaignDailyBudget 
     and count(*) < CampaignTotalBudget) 

接下來,確定兩個「最好」的項目。

,cteTopTwo (CampaignId, Ranking) 
    as (select CampaignId, row_number() over (order by CampgainPPU desc) 
     from cteTargetCampaigns tc 
     inner join Campaigns ca 
     on ca.CampaignId = tc.CampaignId) 

接着,由隨機分配數排隊所有其他廣告活動:

,cteRandom (CampaignId, Ranking) 
    as (select CampaignId, row_number() over (order by RandomNumber) 
     from cteTargetCampaigns 
     where CampaignId not in (select CampaignId 
           from cteTopTwo 
           where Ranking < 3)) 

而且,在最後,拉數據集一起:

select CampaignId 
    from cteTopTwo 
    where Ranking <= 2 
union all select CampaignId 
    from cteRandom 
    where Ranking <= 3 

整上述代碼段,調試錯誤,無效假設以及錯過的要求(例如,從隨機條目中標識前兩項的順序或標誌),並且您應該好。

+0

增加了更多的信息,以排除我最初的問題中的錯誤 – eugeneK 2010-06-15 06:45:00

+0

鑑於OP的修訂,這幾乎是我會採取的方法。 +1用於相交,除了構建廣告系列列表。 – Thomas 2010-06-15 14:59:42

+0

和@Thomas,非常感謝你的回覆,我會在這裏和那裏修改一下,但這個查詢的框架非常重要,而你們兩個都給了我更多的東西。 – eugeneK 2010-06-16 06:16:45

2

我不知道我理解您的文章的這一部分:

它得到5個CampaignVariants爲用戶 進入網站,當我從 用戶 PublisherRegionUID,IP,語言,國家 和地區

我假設「它」是查詢。給予你第二個「下一個條件」的用戶是IP? 「什麼時候從用戶拿走」是什麼意思?這是否意味着您執行查詢時的信息或者是您從查詢中返回的信息?如果是後者,那麼有很多問題需要回答,因爲許多專欄是「多:多」關係的一部分。

無論如何,下面是獲取5個廣告系列的方法,根據您的第二個「下一個條件」,您有一個要過濾掉的IP地址。我還假設你要共計五個活動,這意味着三個隨機的不能包含兩個「最高PPU」。

With 
    ValidCampaigns As 
    (
    Select C.campaignId 
    From Campaigns As C 
     Left Join (Campaigns2IPs As CIP 
      Join IPs 
       On IPs.ipID = CIP.ipID 
        And IPs.ipAddress = @IPAddress) 
      On CIP.campaignId = C.campaignId 
    Where CIP.campaignID Is Null 
    ) 
    CampaignPPURanks As 
    (
    Select C.campaignId 
     , Row_Number() Over (Order By C.campaignPPU desc) As ItemRank 
    From ValidCampaigns As C 
    ) 
    , RandomRanks As 
    (
    Select campaignId 
     , Row_Number() Over (Order By newid() desc) As ItemRank 
    From ValidCampaigns As C 
     Left Join CampaignPPURanks As CR 
      On CR.campaignId = C.campaignId 
       And CR.ItemRank <= 2 
    Where CR.campaignId Is Null 
    ) 
Select ... 
From CampaignPPURanks As CPR 
    Join CampaignVariants As CV 
     On CV.campaignId = CPR.campaignId 
      And CPR.ItemRank <= 2 
Union All   
Select ... 
From RandomRanks As RR 
    Join CampaignVariants As CV 
     On CV.campaignId = RR.campaignId 
      And RR.ItemRank <= 3 
+0

感謝您的輸入。爲了更加清晰,我修改了我的帖子 – eugeneK 2010-06-15 06:06:38

+0

@eugeneK,告訴我們這是什麼問題可能是有幫助的。 – 2010-06-15 06:47:25

+0

@Lieven,PublisherRegionUID過濾器被排除在外。發佈商可以設置其網站中顯示的項目的類別,語言,國家和地區。因此我必須將其納入考慮範圍。 – eugeneK 2010-06-15 06:50:03