多个连接查询只选择每种类型中的一个

时间:2015-10-27 09:57:35

标签: sql-server

我是SQL的新手,所以请不要犹豫,添加有关查询的其他评论。

我努力工作的数据库已经过时了,几乎完全没有限制。

这是我正在处理的查询:

  select cp.id, cp.connectedId, pd.Name, prt.Data, pd.language, prt.FileName, pr.resourceType
from 
[AAES_PAM_DEV].[dbo].[ConnectedProduct] cp
left join [AAES_PAM_DEV].[dbo].[Product] p
on cp.connectedId = p.id
left join [AAES_PAM_DEV].[dbo].[ProductResource] pr
on cp.connectedId = pr.id and cp.Company = pr.Company
inner join [AAES_PAM_DEV].[dbo].[ProductDescription] pd
on cp.connectedId = pd.id and cp.Company = pd.Company
left join [AAES_PAM_DEV].[dbo].[ProductResourceThumbnail] prt
on cp.connectedId = prt.ProductId and cp.Company = prt.CompanyName and pr.fileName = prt.FileName
where pd.language = 'en' order by cp.id

这是结果: enter image description here

我现在要做的是根据resourceType(右边的列)选择行

我只想根据id,connectedId和language选择一个唯一的行。 我还希望它通过查看是否存在类型为&#34的资源类型来选择此行;我"首先,如果没有,那么选择资源类型是什么" S"如果这些都不存在,那么只需要找到它找到的第一行。

这是我想要的一个例子:

enter image description here

正如您所看到的,它是组合键(id,connectedId和language)上的唯一行,并且它只选择resourcetypeid =" I"中的一行。 因此,即使存在许多具有相同组合键的其他行,我也希望它选择一行,其中首先是resourcetypeid =" I"如果那不存在那么我希望它采取resourcetypeid =" S"如果不存在,它可以使用组合键(id,connectedId和language)找到它找到的第一行

我的尝试:

SELECT cp.id, cp.connectedId, pd.language, pr.resourceType
FROM (
  SELECT cp.id, cp.connectedId, pd.language, pr.resourceType
   , DENSE_RANK() OVER(ORDER BY [Priority]) AS [RANK]
  FROM (
    SELECT cp.id, cp.connectedId, pd.language, pr.resourceType
    , CASE pr.resourceType
       WHEN 'I' THEN 1
      WHEN 'S' THEN 2
      ELSE 3
     END AS [Priority]
   FROM [AAES_PAM_DEV].[dbo].[ConnectedProduct] cp
        left join [AAES_PAM_DEV].[dbo].[Product] p
          on cp.connectedId = p.id
        left join [AAES_PAM_DEV].[dbo].[ProductResource] pr
        on cp.connectedId = pr.id and cp.Company = pr.Company
        inner join [AAES_PAM_DEV].[dbo].[ProductDescription] pd
        on cp.connectedId = pd.id and cp.Company = pd.Company
        left join [AAES_PAM_DEV].[dbo].[ProductResourceThumbnail] prt
        on cp.connectedId = prt.ProductId and cp.Company = prt.CompanyName and pr.fileName = prt.FileName
WHERE pd.language = 'en'
GROUP BY cp.id, cp.connectedId, pd.language, pr.resourceType
  ) AS PrioritizedSelect
 ) AS RankedSelect
WHERE [RANK] = 1

这是我得到的错误:

Msg 4104,Level 16,State 1,Line 53 多部分标识符" cp.id"无法受约束。 Msg 4104,Level 16,State 1,Line 53 多部分标识符" cp.connectedId"无法受约束。 Msg 4104,Level 16,State 1,Line 53 多部分标识符" pd.language"无法受约束。 Msg 4104,Level 16,State 1,Line 53 多部分标识符" pr.resourceType"无法受约束。 消息4104,第16级,状态1,第51行 多部分标识符" cp.id"无法受约束。 消息4104,第16级,状态1,第51行 多部分标识符" cp.connectedId"无法受约束。 消息4104,第16级,状态1,第51行 多部分标识符" pd.language"无法受约束。 消息4104,第16级,状态1,第51行 多部分标识符" pr.resourceType"无法受约束。

2 个答案:

答案 0 :(得分:1)

让我们从表格和联接开始。

  1. 您将product外部加入connectedproductconnectedproduct中没有匹配记录时,product中的记录如何存在?这应该是内部联接,或者表名称具有误导性。
  2. 然后,您在productresourceproductdescription上加入外联接表id和内联接表company。因此,当他们id正确关联时,公司怎么会出现不匹配? id 表格主键,对吧?那么,为什么唯一标识的记录会与connectedproduct相关联,但会有另一个company?这看起来很可疑。你是想在这里防范数据不一致吗?
  3. 在您的搜索结果中,我看到很多cp.id为空。表中的记录怎么没有ID?表具有 ID,然后每个记录都有一个用于标识的ID,它根本没有ID列。可空的ID在数据库中没有任何意义。
  4. 然后你只想要"最好的"记录每cp.idcp.connectedIdpd.language。所以你想对你的记录进行排名。您可以使用分析函数ROW_NUMBER来执行此操作,您可以按质量对记录进行排序,并为每组值#1提供最佳记录。之后,您可以将这些结果过滤为仅保留#1记录。

    select id, connectedid, name, data, language, filename, resourcetype
    from
    (
      select 
        cp.id,
        cp.connectedid, 
        pd.name, 
        prt.data, 
        pd.language, 
        prt.filename, 
        pr.resourcetype,
        row_number()
          over(partition by cp.id, cp.connectedId, pd.language
               order by case pr.resourcetype when 'I' then 1 when 'S' then 2 else 3 end) as rn
      from aaes_pam_dev.dbo.connectedproduct cp
      left join aaes_pam_dev.dbo.product p 
        on cp.connectedid = p.id
      left join aaes_pam_dev.dbo.productresource pr
        on cp.connectedid = pr.id 
        and cp.company = pr.company
      inner join aaes_pam_dev.dbo.productdescription pd 
        on cp.connectedid = pd.id 
        and cp.company = pd.company
      left join aaes_pam_dev.dbo.productresourcethumbnail prt 
        on cp.connectedid = prt.productid
        and cp.company = prt.companyname 
        and pr.filename = prt.filename
      where pd.language = 'en' 
    ) ranked
    where rn = 1
    order by id;
    

答案 1 :(得分:0)

基本上,您可以使用该结构构建您的请求:

SELECT Id, ConnectedId, Language, RessourceType
FROM (
  SELECT Id, ConnectedId, Language, RessourceType
   , DENSE_RANK() OVER(ORDER BY [Priority]) AS [RANK]
  FROM (
    SELECT Id, ConnectedId, Language, RessourceType
     , CASE RessourceType
       WHEN 'I' THEN 1
       WHEN 'S' THEN 2
       ELSE 3
     END AS [Priority]
    FROM [ ... ]
    WHERE [ ... ]
    GROUP BY Id, ConnectedId, Language, RessourceType
  ) AS PrioritizedSelect
) AS RankedSelect
WHERE [RANK] = 1