当查询以相同的方式写入时,从3个表中返回不同的结果

时间:2016-09-07 14:34:21

标签: php mysql

你好,我有一个表格,我可以通过他的名字选择艺术家或选择一首歌并选择一个日期范围并从中获取统计数据,我想要实现的基本上是以下,

  • 获得播放次数
  • 获得歌曲数量

问题是我写的两个查询看起来都一样,是否有另一种方法可以更好地解决这个问题?

这是数据库结构

3桌

  • 播放:play_id |日期
  • 歌曲:plid |辅助
  • 艺术家:援助| ARTIST_NAME

示例变量

$artist = SIA
$song = chandelier
$start_date = 2016-09-06
$end_date = 2016-09-07

示例数据库

播放表格

  • A- play_id = 12 | date = 2016-09-06

  • B- play_id = 13 | date = 2016-09-07

  • C- play_id = 14 | date = 2016-09-07

歌曲表

  • A- plid = 12 |援助= 34

  • B-plid = 12 |援助= 34

  • C-plid = 13 |援助= 34

  • D-plid = 14 |援助= 34

  • E-plid = 14 |援助= 34

艺术家表

  • A- aid = 34 | artist_name = SIA

预期结果

  • 每位艺术家的数量= 3

  • B-每位艺术家的歌曲数量= 5

查询歌曲(这是正常工作并计算歌曲的相关性)

$q2 = "
SELECT * 
  FROM songs s
  LEFT 
  JOIN plays p
    ON p.play_id = s.plid
  LEFT 
  JOIN artist a
    ON a.aid = s.aid
 WHERE (a.artist_name = '$artist' OR s.aid = '$song') 
   AND date BETWEEN '$start_date' AND '$end_date'";

查询播放(此播放返回与查询相同的结果,歌曲应返回此艺术家的播放次数)

$q1 = "
SELECT * 
  FROM plays p
  LEFT 
  JOIN songs s
    ON s.plid = p.play_id
  LEFT
  JOIN artist a
    ON  a.aid = s.aid
 WHERE (a.artist_name= '$artist' OR s.aid = '$song') 
   AND date BETWEEN '$start_date' AND '$end_date'";

2 个答案:

答案 0 :(得分:1)

让我们看看第二个问题......

$q1 = "
SELECT * 
  FROM plays p
  LEFT 
  JOIN songs s
    ON s.plid = p.play_id
  LEFT
  JOIN artist a
    ON  a.aid = s.aid
 WHERE (a.artist_name= '$artist' OR s.aid = '$song') 
   AND date BETWEEN '$start_date' AND '$end_date'";

可能需要成为......

$q1 = "
SELECT * 
  FROM plays p
  LEFT JOIN songs s
    ON s.plid = p.play_id
  LEFT JOIN artist a
    ON  a.aid = s.aid
  and (a.artist_name= '$artist' OR s.aid = '$song') 
 WHERE date BETWEEN '$start_date' AND '$end_date'";

正在发生的事情是LEFT连接根据需要生成带有NULL的结果集。但是你有(a.artist_name= '$artist' OR s.aid = '$song') 在where子句中,会导致在左连接中生成的NULLS从结果中排除。

尝试以上代替

答案 1 :(得分:0)

您遇到的问题是由您的数据和查询方式引起的。从样本数据中可以清楚地看出,单个播放可以有多首歌曲。

这意味着,当您列出来自playssongs表格的匹配记录时,记录的数量将会返回由songs表确定,因为它有重复的数据。

要获取播放次数,您需要计算查询返回的不同 play ids的数量。由于song表中的重复,简单计数将返回5。另外,你不需要@xQbert所解释的左连接,所以我只使用内连接,因为你只想要匹配的连接。我还删除了对歌曲的过滤,因为你坚持第二个查询应该返回给定艺术家的播放次数。您可以自由添加该条件。

$q1 = "
SELECT count(distinct p.play_id) as count_of_plays 
  FROM plays p
  INNER 
  JOIN songs s
    ON s.plid = p.play_id
  INNER
  JOIN artist a
    ON  a.aid = s.aid
 WHERE a.artist_name= '$artist' 
   AND date BETWEEN '$start_date' AND '$end_date'";