【问题标题】:Merging SQL query for results that are alike合并 SQL 查询以获得相似的结果
【发布时间】:2011-12-31 03:08:20
【问题描述】:

我现在有一个系统来存储与每个产品相关的产品和标签。

例子

产品:麦克风

标签:音乐、电子产品、音频

有 Tag 表、Product 表和 TagProductMapping 表。第三个表显然将产品映射到标签以实现一对多关系。当我使用 LEFT JOIN 查询麦克风产品时,我得到 3 条几乎重复的记录,除了“TagName”列显然它具有所有 3 个不同的标签。我怎样才能合并这个结果?令人沮丧的是,如果我尝试准确查询 10 个产品,它只会限制为 10 个结果,而实际上并不是 10 个产品。

有人对此有好的想法吗?

编辑:

这是我查询的结果,请注意 3 个 JobId 之间唯一不同的是 CategoryName,它们是标签。

这是我的桌子的样子

-标签映射表:

-标签表

-“产品表”(在这种情况下,它是我的工作表)

这是我的存储过程:

ALTER PROCEDURE [dbo].[JobPostingSelectAll]                       
(                      
    @StartRowIndex     INT,                      
    @PageSize          INT,                      
    @OrderBy           VARCHAR(50),                      
    @OrderByDirection  VARCHAR(4),                      
    @CurrentUserId     INT,            
    @CategoryId     INT                      
)                      
AS                      
 SET NOCOUNT ON                                            



 SELECT         
  JobId,        
  Title,                      
  Answers,          
  UserId,                  
        UserName,        
        ProfileImageName,        
        CategoryId,        
        CategoryName,        
        Fees,            
        DESCRIPTION,                
        DateCreated,      
        UniqueTitle,    
        IsSecured                                
 FROM   (                      
            SELECT J.JobId,        
       J.Title,        
       (SELECT COUNT(ja2.JobId) FROM JobApplication ja2 left join Deliverable d2 ON d2.DeliverableId = ja2.DeliverableId
       WHERE ja2.JobId=j.JobId and (d2.PurchaseCount>0 OR d2.IsFrozen=0)) AS Answers,            
                   J.UserId,        
                   U.UserName,        
                   U.ImageName as ProfileImageName,        
                   J.CategoryId,        
                   C.CategoryName,        
                   J.Fees,        
                   J.Description,                                              
                   J.DateCreated,      
                   J.UniqueTitle,    
                   J.IsSecured,                                                
                   ROW_NUMBER() OVER(                      
                       ORDER BY                  
                       CASE                       
                            WHEN @OrderByDirection = 'asc' AND @OrderBy = 'Answers'             
                            THEN (SELECT COUNT(ja2.JobId) FROM JobApplication ja2 left join Deliverable d2 ON d2.DeliverableId = ja2.DeliverableId
       WHERE ja2.JobId=j.JobId and (d2.PurchaseCount>0 OR d2.IsFrozen=0)) END ASC,            
                       CASE                       
                            WHEN @OrderByDirection = 'asc' AND @OrderBy = 'Answers'             
                            THEN J.DateCreated END DESC,            
                       CASE                       
                            WHEN @OrderByDirection = 'asc' AND @OrderBy = 'Answers'             
                            THEN J.Title END ASC,            
                       CASE                       
                            WHEN @OrderByDirection = 'desc' AND @OrderBy = 'Answers'             
                            THEN (SELECT COUNT(ja2.JobId) FROM JobApplication ja2 left join Deliverable d2 ON d2.DeliverableId = ja2.DeliverableId
       WHERE ja2.JobId=j.JobId and (d2.PurchaseCount>0 OR d2.IsFrozen=0)) END DESC,                                             
      CASE                       
                            WHEN @OrderByDirection = 'desc' AND @OrderBy = 'Answers'             
                            THEN J.DateCreated END DESC,            
                         CASE                       
                            WHEN @OrderByDirection = 'desc' AND @OrderBy = 'Answers'             
                            THEN J.Title END ASC,            
                       CASE WHEN @OrderByDirection = 'asc' AND @OrderBy = 'Fees'             
       THEN J.Fees END ASC,            
       CASE WHEN @OrderByDirection = 'asc' AND @OrderBy = 'Fees'             
       THEN J.DateCreated END DESC,            
        CASE WHEN @OrderByDirection = 'desc' AND @OrderBy = 'Fees'             
       THEN J.Fees END DESC,            
                       CASE WHEN @OrderByDirection = 'desc' AND @OrderBy = 'Fees'             
       THEN J.DateCreated END DESC,            
                       CASE WHEN @OrderByDirection = 'asc' AND @OrderBy = 'DateCreated'             
       THEN J.DateCreated END ASC,                      
                       CASE WHEN @OrderByDirection = 'desc' AND @OrderBy = 'DateCreated'             
       THEN J.DateCreated END DESC            
                   ) AS RowIndex           
            FROM   [JobPosting] J    
                LEFT JOIN TagMapping TM ON J.JobId = TM.QuestionId      
                        LEFT JOIN Categories C ON TM.TagId = C.CategoryID            
            Left Join [User] U ON J.UserId = U.UserID            
            WHERE  J.IsLocked = 0  AND j.IsDeleted = 0                                           
       AND (@CategoryId IS NULL OR  J.CategoryId = @CategoryId)            

        ) AS JobPostingList                      
 WHERE  RowIndex BETWEEN @StartRowIndex AND (@StartRowIndex + @PageSize) - 1             


 SELECT COUNT(J.JobID) AS TotalRecords                      
 FROM   JobPosting J                                      
 WHERE  J.IsLocked = 0 AND J.IsDeleted = 0                        
        AND (@CategoryId IS NULL OR  J.CategoryId = @CategoryId)          


-- select all filecount grouped by Type Of File for specific Job                
SELECT J.JobId, F.MimeType, COUNT(F.FileId) AS FileCount                
FROM                   
JobPosting J  
Left Join Files F ON  F.JobPostingId = J.JobId  
WHERE  J.IsLocked = 0 AND J.IsDeleted = 0                        
        AND (@CategoryId IS NULL OR  J.CategoryId = @CategoryId)          
GROUP BY                                
       F.MimeType,J.JobId  
Having COUNT(F.FileId) > 0

【问题讨论】:

  • 你能发一个表格的例子吗?
  • 发布您的查询..您使用了错误的连接类型,或者您可能想查看 UNION 也许您的内部或左外部连接可能是正确的..但您可能需要一个子查询或在查询中添加/检查空值,如果不查看表并退出查询,也无法判断
  • 标签可以关联多个产品,产品可以有多个标签?如果那是真的,那不是一对多。当您要求“合并”结果时,您是否要求只查看产品一次,然后查看每个标签?
  • 您的意思是每个产品获取一条记录,但在产品的一个字段中列出所有匹配的标签?而不是每个产品三个记录?如果是,您将不得不考虑按产品 ID 和连接标签对结果进行分组。
  • 您想返回每个产品的所有标签,还是只返回具有指定关联标签集的产品?

标签: c# asp.net sql sql-server


【解决方案1】:

您遇到的问题是因为您的数据库结构标准化了每个产品的标签数据(我发现this page 是一个很好的参考)。

当您从 Products 表中 SELECTJOIN 到您的 Tags 表时,请务必记住您没有获得产品列表。相反,您将获得产品标签组合的列表。

如果您想获得前 10 种产品的列表以及它们的标签信息,我建议使用子查询:

select * from 
    (select top 10 * from ProductsTable) TopProducts
    inner join Tagmapping on TopProducts.ProductID = Tagmapping.ProductID
    inner join Tags on Tagmapping.TagID = Tags.TagID

即使这解决了您最初的选择问题,这仍然会产生您在上面显示的那种多重列表,其中只有标签信息因行而异。

可以将输出格式化为具有多个标记条目(可能用逗号分隔)as described here,但这将是您在将数据呈现给用户之前的最后一步,或者通过 SQL或您用作中间人的任何软件层。

【讨论】:

    【解决方案2】:

    我相信如果您对标签名称不感兴趣,您可以选择除标签名称之外的所有列,并使用“选择不同”来仅显示没有标签的产品。不过我可能是错的 =(

    【讨论】:

      猜你喜欢
      • 2011-01-11
      • 1970-01-01
      • 2012-06-14
      • 2020-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-27
      • 1970-01-01
      相关资源
      最近更新 更多