MySQL从表中返回所有匹配项,并指示id是否在另一个表上

时间:2018-03-30 14:39:30

标签: mysql select

如何在选择中返回表示已找到ID的字段?

我的目标是从特定来源(来源)返回所有歌曲(歌曲),检查用户(用户)是否拥有(user_song)。

我所做的查询几乎可以正常工作。如果我删除了'hasSong' (我试图表明用户是否有歌曲),我可以看到所有歌曲。

enter image description here

如果我保持' hasSong',我会看到所有歌曲都为每个用户重复歌曲。 enter image description here

QUERY:

SELECT DISTINCT(song.id) AS id_song, CONCAT(song.article, ' ', song.name) AS name
FROM `song` 
LEFT JOIN `user_song` ON `song`.`id` = `user_song`.`id_song` 
LEFT JOIN `user` ON `user`.`id` = `user_song`.`id_user` 
JOIN `song_source` ON `song`.`id` = `song_source`.`id_song` 
WHERE `song_source`.`id_source` = '1' 
    AND ( `user_song`.`id_user` = '3' OR song.id = song_source.id_song ) 
ORDER BY `song`.`name` ASC

DB:

CREATE TABLE `song` (
  `id` int(11) NOT NULL,
  `article` varchar(10) NOT NULL,
  `name` varchar(150) NOT NULL,
  `shortname` varchar(150) NOT NULL,
  `year` int(11) NOT NULL,
  `artist` int(11) NOT NULL,
  `duration` int(11) NOT NULL,
  `genre` int(11) NOT NULL,
  `updated` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `song_source` (
  `id_song` int(11) NOT NULL,
  `id_source` int(11) NOT NULL
)

CREATE TABLE `source` (
  `id` int(11) NOT NULL,
  `article` varchar(10) NOT NULL,
  `name` varchar(150) NOT NULL,
  `updated` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `user` (
  `id` int(11) NOT NULL,
  `email` varchar(100) NOT NULL,
  `password` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `user_song` (
  `id_user` int(11) NOT NULL,
  `id_song` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

1 个答案:

答案 0 :(得分:1)

规范并不完全清楚,......

要返回来自特定来源(song.id)的所有歌曲(没有重复的id_source='1'值),

以及一个指标,值为0或1,告诉我们user_song中的id_song行是否与id_user = '3'匹配且与特定用户相关,({{ 1}})

类似的东西:

SELECT s.id                                AS id_song
     , MAX( CONCAT(s.article,' ',s.name) ) AS name
     , MAX( IF(us.id_user = '3' ,1,0)    ) AS has_song
  FROM `song` s
  JOIN `song_source` ss 
    ON ss.id_song = s.id
   AND ss.id_source = '1'
  LEFT
  JOIN `user_song` us
    ON us.id_song = s.id
   AND us.id_user = '3'
 GROUP BY s.id
 ORDER BY MAX(s.name)

还有一些其他查询模式会返回相同的结果。例如,我们可以在SELECT列表中使用相关子查询。

SELECT s.id                                AS id_song
     , MAX( CONCAT(s.article,' ',s.name) ) AS name

     , ( SELECT IF( COUNT(us.id_user) >0,1,0)
           FROM `user_song` us 
          WHERE us.id_song = s.id
            AND us.id_user = '3'
       ) AS has_song

  FROM `song` s
  JOIN `song_source` ss
    ON ss.id_song = s.id
   AND ss.id_source = '1'
 GROUP BY s.id
 ORDER BY MAX(s.name)

由于在任何表中都不保证唯一性,因此这些查询很复杂。如果我们有保证,我们就可以省去GROUP BY和聚合函数。

请考虑在表上添加PRIMARY和/或UNIQUE KEY约束,以防止重复。定义表的方式,我们可以向song添加多行,并使用相同的id值。 (那些可能有不同的name值。)

(如果我们有一些唯一性的保证,那么查询将会更简单。)