MySQL - 唯一行,仅对应于 3 个表中的一个

MySQL - unique rows, corresponding to one of 3 tables only

以下查询按预期正确提取数据,但是左连接与 lnk_cat_isrc table 并通过它连接到 catalogue table,如果有则返回重复数据catalogue 中不止一项具有来自 isrc table:

的相同 isrc
SELECT 
                isrc.ISRC,
                isrc.Track_Name,
                isrc.ArtistName,
                isrc.TitleVersion,
                isrc.Track_Time,
                `isrc_performer`.`PerformerName` ,
                `performer_category`.`PerformerCategory` ,
                `isrc_performer`.`PerformerRole` ,
                `isrc`.`isrc_ID`,
                `isrc_performer`.`Perf_ID`

        FROM `isrc`

        LEFT JOIN `isrc_performer` ON (isrc.isrc_ID = isrc_performer.isrc_ID)
        LEFT JOIN `performer_category` ON (performer_category.PerfCat_ID = isrc_performer.PerfCat_ID)
        LEFT JOIN `lnk_cat_isrc` ON (lnk_cat_isrc.isrc_ID = isrc.isrc_ID)
        LEFT JOIN `catalogue` ON (catalogue.ID = lnk_cat_isrc.cat_id) 
        ORDER BY   isrc_ID     desc LIMIT 0 , 10
        ";

我不能在 isrc 上使用 group by,因为 isrc_performer table 一个 isrc 可以有多个表演者。

所以关系是这样的: catalogue table 中的少数项目可以与 isrc table 中的多个相同项目。反过来,每个 isrc 可以在 isrc_performer table.

中有多个条目

我想要的是显示 isrc_performer 中与每个 isrc 相关的所有相应数据,但不对 catalogue table 中的每个项目重复显示。 我还想显示所有其余 "empty" isrcs(那些在 isrc_performer table 中没有任何数据的)

你能给我一些想法吗?

P.S。尽管我没有从 catalogue table 本身提取任何数据,但当用户为 $where_condition 变量定义搜索条件时,我使用它按目录号进行搜索,因此我需要将其保留在查询中。 即 $where_condition = "catalogue.Catalogue LIKE '%test%' OR ISRC LIKE '%test%' OR Track_Name LIKE '%test%' OR ArtistName LIKE '%test%' OR TitleVersion LIKE '%test%' OR PerformerName LIKE '%test%' OR PerformerCategory LIKE '%test%' OR PerformerRole LIKE '%test%'";

------更新:

试图以图形方式表示这 3 个 table 关系中的可能变化:

cat1 - isrc1 - performer1
       isrc2 - performer1
             - performer2
             - performer3

cat2 - isrc2 - performer1
             - performer2
             - performer3
     - isrc3 - performer2
             - performer4

cat3 - isrc4
     - isrc1 - performer1

UPD(已添加图片)

这是屏幕截图。正如您在图 1 中看到的,有 9 行具有相同的 isrc 编号,但是有 3 位重复表演者 Jason、David、Paul。

这是因为根据图片 2,3 个不同的目录项具有与 3 个不同表演者完全相同的 isrc

= 1(isrc) * 3(目录) * 3(表演者) = 9 行输出

我想要的是 Performers 网格只会为每个表演者显示此 isrc 的 3 行。

---重新排列答案以将 "best" 选项放在最上面..但所有这些都是徒劳的.. w/o 来自 lnk_cat_isrc 或目录的任何数据returned,为什么对目录进行过滤会有所不同?我们正在 return 处理所有 isrc,而不考虑任何过滤,因为它是左连接...

所以这给给定的样本数据带来了问题,预期结果是什么。

可能更优雅...(但不确定是否会更快)远离 exists 并简单地使用不同的在子查询中,因此目录查询总是 return 每个 isrc 1 行;解决 1-M 问题保持左连接从而保持 isrc 记录不在目录限制中。 Return 所有 isrc 信息表演者信息(如果存在)、表演者类别信息(如果存在)和目录信息(如果且仅当它与目录过滤器匹配时)。

SELECT isrc.ISRC
    , isrc.Track_Name
    , isrc.ArtistName
    , isrc.TitleVersion
    , isrc.Track_Time
    ,`isrc_performer`.`PerformerName` 
    ,`performer_category`.`PerformerCategory` 
    ,`isrc_performer`.`PerformerRole` 
    ,`isrc`.`isrc_ID`
    ,`isrc_performer`.`Perf_ID`
FROM `isrc`
LEFT JOIN `isrc_performer` 
  ON isrc.isrc_ID = isrc_performer.isrc_ID
LEFT JOIN `performer_category` 
  ON performer_category.PerfCat_ID = isrc_performer.PerfCat_ID
LEFT JOIN (SELECT distinct lnk_cat_isrc.isrc_ID
           FROM `lnk_cat_isrc` 
           INNER JOIN `catalogue` 
             ON catalogue.ID = lnk_cat_isrc.cat_id
           WHERE...) DCat
   ON Dcat.isrc_ID = isrc.isrc_ID
ORDER BY   isrc_ID     desc 
LIMIT 0 , 10;

正如您所指出的,连接导致了问题。所以消除连接并使用存在符号。 Distinct 也可以工作,因为您没有 selecting 目录中的任何值;虽然存在应该更快。

快速但不包括所有 isrc 记录...(不确定为什么存在或不存在应该将它们带回...)

SELECT isrc.ISRC
     , isrc.Track_Name
     ,isrc.ArtistName
     ,isrc.TitleVersion
     ,isrc.Track_Time
     ,`isrc_performer`.`PerformerName` 
     ,`performer_category`.`PerformerCategory` 
     ,`isrc_performer`.`PerformerRole` 
     ,`isrc`.`isrc_ID`
     ,`isrc_performer`.`Perf_ID`
    FROM `isrc`
    LEFT JOIN `isrc_performer` 
      ON (isrc.isrc_ID = isrc_performer.isrc_ID)
    LEFT JOIN `performer_category` 
      ON (performer_category.PerfCat_ID = isrc_performer.PerfCat_ID)
    WHERE EXISTS (SELECT * 
                  FROM  `lnk_cat_isrc` 
                  INNER JOIN `catalogue` 
                    ON catalogue.ID = lnk_cat_isrc.cat_id
                   --and your other criteria
                  WHERE (lnk_cat_isrc.isrc_ID = isrc.isrc_ID)
                  ) 
     OR NOT EXISTS (SELECT * 
                    FROM `lnk_cat_isrc` 
                    WHERE lnk_cat_isrc.isrc_ID = isrc.isrc_ID
    ORDER BY isrc_ID desc 
    LIMIT 0 , 10

或使用select distinct simple straight forward;但是很慢

 SELECT isrc.ISRC
     , isrc.Track_Name
     ,isrc.ArtistName
     ,isrc.TitleVersion
     ,isrc.Track_Time
     ,`isrc_performer`.`PerformerName` 
     ,`performer_category`.`PerformerCategory` 
     ,`isrc_performer`.`PerformerRole` 
     ,`isrc`.`isrc_ID`
     ,`isrc_performer`.`Perf_ID`
  FROM `isrc`
  LEFT JOIN `isrc_performer` 
    ON (isrc.isrc_ID = isrc_performer.isrc_ID)
  LEFT JOIN `performer_category` 
    ON (performer_category.PerfCat_ID = isrc_performer.PerfCat_ID)
  LEFT JOIN `lnk_cat_isrc` 
    ON (lnk_cat_isrc.isrc_ID = isrc.isrc_ID)
  LEFT JOIN `catalogue` 
    ON (catalogue.ID = lnk_cat_isrc.cat_id) 
   --AND (other criteria on catalog here, cause in a where clause you left joins will behave like inner joins)
  ORDER BY isrc_ID desc 
  LIMIT 0 , 10;