以下是故事:我必须实现过滤器。在此过滤器中,我会过滤某些类别。 其中一个过滤器是“最喜欢的”过滤器(@includeFavourites)。
我有这个庞大的SQL,有分页和排序等等。
现在,当点击过滤器中的“includeFavourites”选项时,我还必须从不同的表中选择唯一的ID(这些条目存储在不同的数据表中),其中存储了收藏夹。 我尝试过左外连接,但它返回主表中每条记录的“收藏数”记录。 Coalesce根本没有帮助。
这是我的SQL:
--this is needed because stored procedure must know how many days are selected
DECLARE @daysCount int
SET @daysCount = 0
IF (@mon IS NOT NULL)
BEGIN
SET @daysCount = @daysCount+1
END
IF (@tue IS NOT NULL)
BEGIN
SET @daysCount = @daysCount+1
END
IF (@wed IS NOT NULL)
BEGIN
SET @daysCount = @daysCount+1
END
IF (@thu IS NOT NULL)
BEGIN
SET @daysCount = @daysCount+1
END
IF (@fri IS NOT NULL)
BEGIN
SET @daysCount = @daysCount+1
END
IF (@sat IS NOT NULL)
BEGIN
SET @daysCount = @daysCount+1
END
IF (@sun IS NOT NULL)
BEGIN
SET @daysCount = @daysCount+1
END
-- Insert statements for procedure here
SELECT * FROM (
SELECT ROW_NUMBER() OVER
(
ORDER BY
CASE WHEN @OrderBy = 'ND' THEN title END DESC,
CASE WHEN @OrderBy = 'NA' THEN title END,
CASE WHEN @OrderBy = '' THEN title END,
CASE WHEN @OrderBy = 'RD' THEN authorRating END DESC,
CASE WHEN @OrderBy = 'RA' THEN authorRating
) AS Row,
Articles.ArticleId, Articles.userId, Articles.timestamp as datePosted, users.screenName,
defaultSmallImagePath, authorRating, ArticleCosts, title,
FROM Articles
LEFT OUTER JOIN
Users on Articles.userId = Users.userId
LEFT OUTER JOIN
ArticleAdditionalInformation ON ArticleAdditionalInformation.ArticleId = Articles.ArticleId
--JOIN FOR CONTINENT
LEFT OUTER JOIN
Codings as Continent ON Continent.codingKeyId = ArticleAdditionalInformation.continentId AND Continent.languageId = @languageId
-- JOIN FOR COUNTRY
LEFT OUTER JOIN
CodingsAssociated as Country ON Country.codingKeyId = ArticleAdditionalInformation.countryId AND Country.languageId = @languageId
-- JOIN FOR Article TRANSLATION DATA
LEFT OUTER JOIN
ArticlesTranslations ON ArticlesTranslations.ArticleId = Articles.ArticleId AND ArticlesTranslations.languageId=@languageId
LEFT OUTER JOIN
ArticleCategories ON ArticleCategories.ArticleId = Articles.ArticleId
WHERE
(
ArticleCategories.categorieId =1 OR ArticleCategories.categorieId =2 OR
ArticleCategories.categorieId =3 OR ArticleCategories.categorieId =4 OR
ArticleCategories.categorieId = 5
) AND
(ArticlesTranslations.title LIKE '%' + @searchString + '%' OR @searchString IS NULL)
-- COST filter
AND
(ArticleCosts < @cost OR @cost = 0)
AND
(ArticleCosts > 0 OR @cost = 0)
--END cost filter
-- EXCLUDE already stored for selected days
AND Articles.ArticleId -- exclude these ArticleIds
NOT IN
(
SELECT DailyContent.ArticleId
FROM DailyContent
WHERE
sectionId=@sectionId AND
(
weekDayId=@mon OR
weekDayId=@tue OR
weekDayId=@wed OR
weekDayId=@thu OR
weekDayId=@fri OR
weekDayId=@sat OR
weekDayId=@sun
)
GROUP BY
DailyContent.ArticleId
HAVING
(COUNT(sectionId) = @daysCount)
)
-- END exclude
) p
WHERE (Row > @startRowIndex AND Row <=@startRowIndex + @pageSize)
ORDER BY Row
END
所以,当@includeFavourites参数不为空时,我只想在收藏表中包含唯一的articleIds。
任何提示都将非常感谢;)
我正在使用SQL Server 2008。
答案 0 :(得分:0)
试试这个 -
DECLARE @daysCount INT
SELECT @daysCount =
ISNULL(@mon, 0) + -- if @mon = 1, @tue = 2, .... 1 + (2-1)=1 + (3-2)=1 + ...
ISNULL(@tue - 1, 0) +
ISNULL(@wed - 2, 0) +
ISNULL(@thu - 3, 0) +
ISNULL(@fri - 4, 0) +
ISNULL(@sat - 5, 0) +
ISNULL(@sun - 6, 0)
SELECT *
FROM (
SELECT ROW_NUMBER() OVER
(
ORDER BY
CASE WHEN @OrderBy = 'ND' THEN title END DESC,
CASE WHEN @OrderBy IN ('NA', '') THEN title END,
CASE WHEN @OrderBy = 'RD' THEN authorRating END DESC,
CASE WHEN @OrderBy = 'RA' THEN authorRating
) AS [Row]
, a.ArticleId
, a.userId
, a.[timestamp] as datePosted
, u.screenName
, defaultSmallImagePath
, authorRating
, ArticleCosts
, title
FROM dbo.Articles a -- always use schema and alias
LEFT JOIN dbo.Users u on a.userId = u.userId -- OUTER is unnecessary
LEFT JOIN dbo.ArticleAdditionalInformation aai ON aai.ArticleId = a.ArticleId
LEFT JOIN dbo.Codings cd ON cd.codingKeyId = aai.continentId AND cd.languageId = @languageId
LEFT JOIN dbo.CodingsAssociated c ON c.codingKeyId = aai.countryId AND c.languageId = @languageId
LEFT JOIN dbo.ArticlesTranslations at ON at.ArticleId = a.ArticleId AND at.languageId = @languageId
LEFT JOIN dbo.ArticleCategories ac ON ac.ArticleId = a.ArticleId
WHERE ac.categorieId IN (1, 2, 3, 4, 5)
AND (
at.title LIKE '%' + @searchString + '%'
OR
@searchString IS NULL
)
AND (ArticleCosts < @cost OR @cost = 0)
AND (ArticleCosts > 0 OR @cost = 0)
AND a.ArticleId NOT IN (
SELECT dc2.ArticleId
FROM dbo.DailyContent dc2
WHERE sectionId = @sectionId
AND (
weekDayId % @daysCount = 0 -- possible it's works
--weekDayId = @mon OR
--weekDayId = @tue OR
--weekDayId = @wed OR
--weekDayId = @thu OR
--weekDayId = @fri OR
--weekDayId = @sat OR
--weekDayId = @sun
)
GROUP BY dc2.ArticleId
HAVING COUNT(sectionId) = @daysCount
)
) p
WHERE [Row] BETWEEN @startRowIndex AND @startRowIndex + @pageSize
--ORDER BY [Row] -- ROW_COUNT already sorted your rows