Guest User

Untitled

a guest
Jan 31st, 2014
1,389
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
T-SQL 18.41 KB | None | 0 0
  1. IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[sp_getPropertiesShortContent]') AND type in (N'P', N'PC'))
  2. DROP PROCEDURE [dbo].[sp_getPropertiesShortContent]
  3. GO
  4. SET ANSI_NULLS ON
  5. GO
  6. SET QUOTED_IDENTIFIER ON
  7. GO
  8.  
  9. CREATE procedure [dbo].[sp_getPropertiesShortContent] (
  10.     @properties varchar(max),
  11.     @destinationFilterPassedProperties varchar(max) = null,
  12.     @language_code varchar(10) = 'en-US',
  13.     @primary_sorting int = null,
  14.     @reverse_primary_sorting bit = 0,
  15.     @secondary_sorting int = null,
  16.     @reverse_secondary_sorting bit = 0,
  17.     @name_filter nvarchar(max) = null,
  18.     @rating_filter varchar(100) = null,
  19.     @chain_filter varchar(100) = null,
  20.     @amenity_filter varchar(100) = null,
  21.     @filter_disabling_allowed bit = 0,
  22.     @page_index int = 1,
  23.     @page_size int = 25,
  24.     @use_old_paging bit = 0,
  25.     @first_product_number int = null,
  26.     @last_product_number int = null
  27.     )
  28. as
  29. begin
  30.     -----------------------------------------------------------------------------
  31.     -- Step 0. Initialize parameters
  32.     -----------------------------------------------------------------------------
  33.     declare @language_id int
  34.     select @language_id = language_id from languages where code = @language_code
  35.  
  36.     declare @step0Ids table (id int, apiFilterPassed bit, sequenceNumber int identity)
  37.  
  38.     insert into @step0Ids
  39.         select * from fn_SplitStringWithCodeNames(@properties, ';', ',')
  40.  
  41.     declare @destinationFilterPassedPropertiesTbl table (id int)
  42.  
  43.     if @destinationFilterPassedProperties is not null
  44.         insert into @destinationFilterPassedPropertiesTbl
  45.             select * from
  46.                 fn_SplitStringToIntegers(@destinationFilterPassedProperties, ';')
  47.  
  48.     declare @ratings table (rating float)
  49.     if (@rating_filter is not null)
  50.         insert into @ratings
  51.             select * from fn_SplitString(@rating_filter, ';')
  52.  
  53.     declare @amenities table (id int)
  54.     if (@amenity_filter is not null)
  55.         insert into @amenities
  56.             select * from fn_SplitStringToIntegers(@amenity_filter, ';')
  57.  
  58.     declare @SORTING_BY_NAME int
  59.     set @SORTING_BY_NAME = 1
  60.  
  61.     declare @SORTING_BY_RATING int
  62.     set @SORTING_BY_RATING = 2
  63.  
  64.     -----------------------------------------------------------------------------
  65.     -- Step 1. Apply filtering to the list
  66.     -----------------------------------------------------------------------------
  67.     declare @step1Ids table (id int, sequenceNumber int identity )
  68.    
  69.     insert into @step1Ids
  70.         select p.id from @step0Ids p
  71.             inner join properties a (nolock) on p.id = a.property_id
  72.             left outer join propertyInformation b (nolock) on
  73.                 b.property_id=a.property_id and b.language_id=@language_id
  74.         where
  75.             -- filtering done by API
  76.             p.apiFilterPassed = 1
  77.         and
  78.             -- name filter
  79.             ((@name_filter is null)
  80.              or (ltrim(isnull(b.[name], a.[name])) like ('%' + @name_filter + '%'))
  81.             )
  82.         and
  83.             -- rating filter
  84.             ((@rating_filter is null)
  85.              or (a.star_rating in (select rating from @ratings)))
  86.         and
  87.             -- amenity filter
  88.             ((@amenity_filter is null)
  89.             or ((select count(*)
  90.                 from dbo.propertyAmenityReference par
  91.                 inner join @amenities a on a.id = par.property_amenity_id  
  92.                 where par.property_id = p.id) = (select count(*) from @amenities))
  93.             )
  94.         order by sequenceNumber
  95.    
  96.     -----------------------------------------------------------------------------
  97.     -- Step 2. Disable filter if no property satisfies filtering criteria and
  98.     --         filter disabling is allowed
  99.     --         and apply destination filter
  100.     -----------------------------------------------------------------------------
  101.     declare @filterDisabled bit
  102.     set @filterDisabled = 0
  103.  
  104.     declare @step2Ids table (id int, sequenceNumber int identity )
  105.     declare @filteredPropertiesIDs table (id int, sequenceNumber int identity )
  106.  
  107.     if ((select count(*) from @step1Ids) = 0 and @filter_disabling_allowed = 1)
  108.     begin
  109.         insert into @step2Ids
  110.             select id from @step0Ids
  111.         set @filterDisabled = 1
  112.     end
  113.     else
  114.     begin
  115.         insert into @step2Ids
  116.             select id from @step1Ids
  117.     end
  118.  
  119.     -- Store filtered properties.
  120.     insert into @filteredPropertiesIDs
  121.         select id from @step2Ids
  122.  
  123.     -- Apply destination filter
  124.     if @destinationFilterPassedProperties is not null
  125.     begin
  126.         delete from @step2Ids
  127.  
  128.         insert into @step2Ids
  129.             select fp.id
  130.             from @filteredPropertiesIDs fp
  131.             inner join @destinationFilterPassedPropertiesTbl dfp
  132.                 on fp.id = dfp.id
  133.     end
  134.  
  135.     declare @destinationsFilterDisabled bit
  136.     set @destinationsFilterDisabled = 0
  137.  
  138.     -- Clear destinations filter if no hotel satisfies filtering criteria
  139.     if ((select count(*) from @step2Ids) = 0 and @filter_disabling_allowed = 1)
  140.     begin
  141.         delete from @step2Ids
  142.  
  143.         insert into @step2Ids
  144.             select fp.id
  145.             from @filteredPropertiesIDs fp
  146.  
  147.         set @destinationsFilterDisabled = 1
  148.     end
  149.  
  150.     --select * from @step2Ids
  151.  
  152.     -----------------------------------------------------------------------------
  153.     -- Step 3. Apply sorting to the list
  154.     -----------------------------------------------------------------------------
  155.     declare @sortings table (sortingId int, reverseSorting bit)
  156.     declare @sorting int
  157.     declare @reverse_sorting bit
  158.  
  159.     declare @step3Ids table (id int, sequenceNumber int identity )
  160.     declare @step3IdsTemp table (id int, sequenceNumber int identity )
  161.  
  162.     insert into @step3Ids select id from @step2Ids
  163.  
  164.     insert into @sortings values (@secondary_sorting, @reverse_secondary_sorting)
  165.     insert into @sortings values (@primary_sorting, @reverse_primary_sorting)
  166.  
  167.     declare sortingCursor cursor local fast_forward for
  168.         select * from @sortings
  169.     open sortingCursor
  170.     fetch from sortingCursor into @sorting, @reverse_sorting
  171.  
  172.     while @@FETCH_STATUS = 0
  173.     begin      
  174.         if (@sorting is not null and @sorting in (1,2))
  175.         begin  
  176.             delete from @step3IdsTemp
  177.             insert into @step3IdsTemp select id from @step3Ids
  178.  
  179.             delete from @step3Ids
  180.  
  181.             if (@sorting = @SORTING_BY_NAME)
  182.             begin
  183.                 -- Sorting queries are dublicated because I have not found
  184.                 -- any way to reverse soring order by using one "select" operator
  185.                 -- in case when sorting is done by nvarchar field.
  186.                 -- Please contact me if you know one.
  187.                 -- I am also can't use separate algorithm step to reverse sorting
  188.                 -- order because it will also reverse previous sortings. //Yakov Zh.
  189.                 if (@reverse_sorting = 0)
  190.                     insert into @step3Ids
  191.                         select p.id from @step3IdsTemp p
  192.                             inner join properties a (nolock) on p.id = a.property_id
  193.                             left outer join propertyInformation b (nolock) on
  194.                                 b.property_id=a.property_id and b.language_id=@language_id
  195.                         order by ltrim(isnull(b.[name], a.[name]))
  196.                 else
  197.                     insert into @step3Ids
  198.                         select p.id from @step3IdsTemp p
  199.                             inner join properties a (nolock) on p.id = a.property_id
  200.                             left outer join propertyInformation b (nolock) on
  201.                                 b.property_id=a.property_id and b.language_id=@language_id
  202.                         order by ltrim(isnull(b.[name], a.[name])) desc, p.sequenceNumber
  203.             end else if (@sorting = @SORTING_BY_RATING) -- Product rating
  204.             begin
  205.                 insert into @step3Ids
  206.                     select p.id from @step3IdsTemp p
  207.                         inner join properties a (nolock) on p.id = a.property_id
  208.                     order by
  209.                         case @reverse_sorting
  210.                             when 0 then coalesce(a.star_rating, 0)
  211.                             else coalesce(-a.star_rating, -0)
  212.                         end,
  213.                         p.sequenceNumber
  214.             end
  215.  
  216.         end
  217.  
  218.         fetch from sortingCursor into @sorting, @reverse_sorting
  219.     end
  220.  
  221.     close sortingCursor
  222.     deallocate sortingCursor
  223.     -----------------------------------------------------------------------------
  224.     -- Step 4. Apply paging to the list
  225.     -----------------------------------------------------------------------------
  226.     declare @step4Ids table (id int, sequenceNumber int identity (0,1))
  227.  
  228.     declare @pagingEnabled bit
  229.     set @pagingEnabled = 1
  230.  
  231.     if (@use_old_paging = 1)
  232.     begin
  233.         declare @step4IdsTemp table (id int, sequenceNumber int identity (0,1))
  234.  
  235.         insert into @step4IdsTemp
  236.             select id from @step3Ids
  237.             order by sequenceNumber    
  238.  
  239.         insert into @step4Ids
  240.             select id from @step4IdsTemp
  241.             where @first_product_number <= sequenceNumber
  242.                   and sequenceNumber <= @last_product_number
  243.             order by sequenceNumber    
  244.     end
  245.  
  246.     if (select count(*) from @step3Ids) <= @page_size
  247.        and @use_old_paging = 0
  248.     begin
  249.         set @pagingEnabled = 0 
  250.    
  251.         insert into @step4Ids
  252.             select id from @step3Ids
  253.             order by sequenceNumber
  254.     end
  255.  
  256.     declare @firstProductNumber int
  257.  
  258.     declare @pages table (
  259.             pageNumber int identity (0,1),
  260.             begining nvarchar,
  261.             ending nvarchar,
  262.             first_product_number int,
  263.             last_product_number int,
  264.             is_simple bit,
  265.             is_disabled bit)
  266.  
  267.     if not (@primary_sorting in (@SORTING_BY_NAME, @SORTING_BY_RATING))
  268.        and @pagingEnabled = 1 and @use_old_paging = 0
  269.     begin
  270.         declare @step4Tmp table (id int, sequenceNumber int identity (0,1))
  271.         insert into @step4Tmp select id from @step3Ids
  272.         declare @lastProductNumber int
  273.         declare @numberOfProducts int
  274.         select @numberOfProducts = count(*) from @step3Ids
  275.  
  276.         set @firstProductNumber = 0
  277.  
  278.         while @firstProductNumber < @numberOfProducts
  279.         begin
  280.             if @lastProductNumber >= @numberOfProducts
  281.                 set @lastProductNumber = @numberOfProducts - 1
  282.  
  283.             insert into @pages values
  284.                 (null,
  285.                  null,
  286.                  @firstProductNumber,
  287.                  @page_size - 1,
  288.                  1,
  289.                  0)
  290.             set @firstProductNumber = @firstProductNumber + @page_size
  291.         end
  292.  
  293.  
  294.         set @firstProductNumber = @page_index * @page_size
  295.         set @lastProductNumber = (@page_index + 1) * @page_size - 1
  296.  
  297.         insert into @step4Ids
  298.             select id from @step4Tmp
  299.                 where sequenceNumber >= @firstProductNumber
  300.                   and sequenceNumber <= @lastProductNumber     
  301.     end
  302.    
  303.     if @primary_sorting = @SORTING_BY_NAME
  304.        and @pagingEnabled = 1 and @use_old_paging = 0
  305.     begin
  306.         -- create pages
  307.  
  308.         -- create and fill table with first letters of hotel names
  309.         declare @hotelNames table (id int, firstLetter nchar, sequenceNumber int identity)
  310.  
  311.         insert into @hotelNames
  312.             select p.id,
  313.                    upper(substring(ltrim(isnull(b.[name], a.[name])),1,1))
  314.             from @step3Ids p
  315.                 inner join properties a (nolock) on p.id = a.property_id
  316.                 left outer join propertyInformation b (nolock) on
  317.                     b.property_id=a.property_id and b.language_id=@language_id
  318.             order by p.sequenceNumber
  319.  
  320.         -- Create name groups. One group for each letter and one special group for numbers
  321.         declare @namesGroups table (firstLetter nchar, entries int)
  322.        
  323.         declare @letter nchar(1)
  324.         declare @entriesCount int
  325.         declare @numericEntriesCount int
  326.  
  327.         -- We need a group for numbers if @numericEntriesCount will be greater than zero
  328.         select @numericEntriesCount = count(*)
  329.         from @hotelNames
  330.         where ascii(firstLetter) >= ascii('0') and ascii(firstLetter) <= ascii('9')
  331.  
  332.         -- Fill groups with letters from a to z or from z to a if sorting order is reversed.
  333.         if (@reverse_primary_sorting = 0)
  334.             set @letter = 'A'
  335.         else
  336.             set @letter = 'Z'
  337.  
  338.         while(ascii(@letter) <= ascii('Z')
  339.               and ascii(@letter) >= ascii('A'))
  340.         begin
  341.             select @entriesCount = count(firstLetter)
  342.             from @hotelNames
  343.             where firstLetter = @letter
  344.  
  345.             insert into @namesGroups
  346.             values (@letter, @entriesCount)
  347.  
  348.             if (@reverse_primary_sorting = 0)          
  349.                 set @letter = char(ascii(@letter) + 1)
  350.             else
  351.                 set @letter = char(ascii(@letter) - 1)
  352.         end
  353.  
  354.         -- Create pages
  355.         declare @firstLetter nchar
  356.         declare @currentLetter nchar
  357.         declare @currentGroupCount int
  358.         declare @currentPageCount int
  359.  
  360.         declare groupCursor cursor for select * from @namesGroups
  361.         open groupCursor
  362.    
  363.         fetch from groupCursor into @currentLetter, @currentGroupCount
  364.         set @currentPageCount = 0
  365.        
  366.         -- add page for numbers if sorting is not reversed
  367.         if (@reverse_primary_sorting = 0 and @numericEntriesCount > 0)
  368.                 insert into @pages values ('0', '9', null, null, 0, 0)
  369.  
  370.         declare @start_new_page bit
  371.         set @start_new_page = 1
  372.    
  373.         while @@FETCH_STATUS = 0
  374.         begin  
  375.             if (@start_new_page = 1) -- We have added a page in previous iteration.
  376.             begin
  377.                 -- Start new page
  378.                 set @firstLetter = @currentLetter -- remember first letter of new page
  379.                 set @start_new_page = 0          
  380.             end
  381.    
  382.             -- Check if we need to finish current page.
  383.             -- We need to finish page when number of hotels in current page is
  384.             -- greater than @page_size. Letters with zero hotels
  385.             -- starting on it are assigned to current page to fill gaps in alphabet.
  386.             if @currentGroupCount + @currentPageCount >= @page_size
  387.                 and @currentGroupCount is not null
  388.             begin
  389.                 insert into @pages values
  390.                     (@firstLetter, @currentLetter, null, null, 0, 0)
  391.                 set @currentPageCount = 0
  392.                 set @start_new_page = 1 -- We need to know that we started a new page
  393.                                         -- on next iteration to remember next page's
  394.                                         -- starting letter.
  395.             end
  396.             else
  397.             begin
  398.                 -- no need to finish page. Update hotels counter only.
  399.                 set @currentPageCount = @currentPageCount + @currentGroupCount
  400.             end
  401.                        
  402.             fetch from groupCursor into @currentLetter, @currentGroupCount
  403.         end
  404.  
  405.         -- if a page is not finished on last iteration -
  406.         -- finish it and add to the list
  407.         if (@start_new_page = 0)
  408.             insert into @pages values
  409.                 (@firstLetter, @currentLetter, null, null, 0, 0)
  410.  
  411.         -- add page for numbers if sorting is reversed
  412.         if (@reverse_primary_sorting = 1 and @numericEntriesCount > 0)
  413.                 insert into @pages values ('0', '9', null, null, 0, 0)
  414.  
  415.         -- Pages are added. Now select hotels for selected page.
  416.  
  417.         -- if order is reversed - replace Begining and Ending for convinience
  418.         declare @currentPageStart nchar
  419.         declare @currentPageEnd nchar
  420.        
  421.         if @reverse_primary_sorting = 0
  422.             select
  423.                 @currentPageStart = Begining,
  424.                 @currentPageEnd = Ending
  425.             from @pages
  426.             where pageNumber = @page_index
  427.         else
  428.             select
  429.                 @currentPageStart = Ending,
  430.                 @currentPageEnd = Begining
  431.             from @pages
  432.             where pageNumber = @page_index
  433.  
  434.         -- Select hotels.
  435.         insert into @step4Ids
  436.             select id from @hotelNames
  437.                 where ascii(firstLetter) >= ascii(@currentPageStart)
  438.                   and ascii(firstLetter) <= ascii(@currentPageEnd)
  439.             order by sequenceNumber
  440.  
  441.         close groupCursor
  442.         deallocate groupCursor
  443.     end
  444.  
  445.     if @primary_sorting = @SORTING_BY_RATING
  446.        and @pagingEnabled = 1 and @use_old_paging = 0
  447.     begin
  448.         -- Enumerate and add all possible rating pages
  449.         declare @ratingPages table
  450.             (fromValue int, toValue int, issimple bit, sequenceNumber int identity)
  451.         insert into @ratingPages values (null, null, 1) -- (uncategorized)
  452.         insert into @ratingPages values (0, 1, 0) -- 1 star
  453.         insert into @ratingPages values (1, 2, 0) -- ...
  454.         insert into @ratingPages values (2, 3, 0) -- ...
  455.         insert into @ratingPages values (3, 4, 0) -- ...
  456.         insert into @ratingPages values (4, 5, 0) -- 5 stars
  457.                    
  458.         insert into @pages
  459.             select
  460.                 r.fromValue,
  461.                 r.toValue,
  462.                 null,
  463.                 null,
  464.                 r.isSimple,
  465.                 (select (case count(*) when 0 then 1 else 0 end)
  466.                 from @step3Ids p
  467.                     inner join properties a (nolock) on p.id = a.property_id
  468.                 where floor(a.star_rating) = r.toValue
  469.                     or (r.toValue is null  
  470.                         and (a.star_rating is null or a.star_rating = 0)))
  471.             from @ratingPages r
  472.             where (r.isSimple = 0) -- Do not display non-rated hotels page if no non-rated hotels exists.
  473.                   or exists(select * from @step3Ids p
  474.                             inner join properties a (nolock) on p.id = a.property_id
  475.                             where (a.star_rating is null or a.star_rating = 0))
  476.             order by case @reverse_primary_sorting
  477.                      when  0 then sequenceNumber
  478.                              else -sequenceNumber
  479.                      end
  480.  
  481.         while (select count(*) from @step4Ids) = 0
  482.         begin
  483.             -- Select hotels.
  484.             insert into @step4Ids
  485.                 select id from @step3Ids p
  486.                     inner join properties a (nolock) on p.id = a.property_id
  487.                     inner join @pages pg on pg.pageNumber = @page_index
  488.                 where floor(a.star_rating) = pg.ending
  489.                     or (pg.ending is null
  490.                         and (a.star_rating is null or a.star_rating = 0))
  491.                 order by p.sequenceNumber
  492.            
  493.             set @page_index = @page_index + 1
  494.         end
  495.         set @page_index = @page_index - 1
  496.     end
  497.  
  498.     -----------------------------------------------------------------------------
  499.     -- Step 5. Select content
  500.     -----------------------------------------------------------------------------
  501.  
  502.     -- Hotel content
  503.     select
  504.         p.sequenceNumber,
  505.         a.[property_id] as PropertyID,
  506.         a.[postal_code] as PostalCode,
  507.         a.[latitude] as Latitude,
  508.         a.[longitude] as Longitude,
  509.         a.[longitude] as Longitude,
  510.         a.[star_rating] as StarRating,
  511.         a.[city_code] as CityCode,
  512.         isnull(b.[city_name], a.[city_name]) as CityName,
  513.         a.[province_code] as ProvinceCode,
  514.         isnull(b.[province_name], a.[province_name]) as ProvinceName,
  515.         a.[country_code] as CountryCode,
  516.         isnull(b.[country_name], a.[country_name]) as CountryName,
  517.         ltrim(isnull(b.[name], a.[name])) as [Name],
  518.         a.[small_exterior_url] as SmallExteriorUrl,
  519.         a.[large_exterior_url] as LargeExteriorUrl,
  520.         a.[email] as Email,
  521.         isnull(b.[address_line_1], a.[address_line_1]) as AddressLine1,
  522.         isnull(b.[address_line_2], a.[address_line_2]) as AddressLine2,
  523.         isnull(b.[address_line_3], a.[address_line_3]) as AddressLine3,
  524.         isnull(b.[address_line_4], a.[address_line_4]) as AddressLine4,
  525.         isnull(b.[short_description], a.[short_description]) as ShortDescription,
  526.         a.[smoking_type_id] as SmokingTypeID
  527.     from @step4Ids p
  528.         inner join properties a (nolock) on p.id = a.property_id
  529.         left outer join propertyInformation b (nolock) on b.property_id=a.property_id and b.language_id=@language_id
  530.         left join propertyInformation c (nolock) on c.property_id=a.property_id and c.language_id=1
  531.     order by p.sequenceNumber
  532.  
  533.     -- Select pages
  534.     select
  535.         pageNumber as PageIndex,
  536.         null as DisplayText,
  537.         begining as Beginning,
  538.         ending as Ending,
  539.         first_product_number as FirstProductNumber,
  540.         last_product_number as LastProductNumber,
  541.         0 as IsSeparator,
  542.         is_simple as IsSimple,
  543.         is_disabled as IsDisabled
  544.     from @pages
  545.  
  546.     -- Select misc scalar values
  547.  
  548.     declare @sequenceNumbers table (id int, sequenceNumber int identity (0,1))
  549.     insert into @sequenceNumbers select id from @step3Ids
  550.  
  551.     select @filterDisabled as FilterDisabled,
  552.            @destinationsFilterDisabled as DestinationsFilterDisabled,  
  553.            (select count(*) from @step3Ids) as NumberOfProducts,
  554.            (select count(*) from @step0Ids) as TotalNumberOfProducts,
  555.            (select top 1 sequenceNumber from @sequenceNumbers
  556.             where id = (select top 1 id from @step4Ids)) as FirstProductNumber,
  557.             @page_index as PageIndex
  558.  
  559.     -- List of property ids for properies which passed the filter
  560.  
  561.     select id as PropertyID
  562.     from @filteredPropertiesIDs
  563. end
Advertisement
Add Comment
Please, Sign In to add comment