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