0

我有一个查询数据库以获取最新曲目的 mysql 语句。但是,由于数据库是部分规范化的,因此 ID 位于不同的表中。在查询中,我从艺术家表中获取艺术家 ID 并将它们放入变量中。然后将变量解析为一个查询,该查询查看曲目以找到最新的曲目,这就是问题所在。由于 $artist 变量可以包含大量 ID,所有这些 ID 都被解析到查询中,即使我在查询中设置了 LIMIT,结果也是几个 url 放在一起。

请记住,我无法限制艺术家查询,因为我需要从表中获取所有艺术家并从所有艺术家中找到最新的曲目。

如何在不限制艺术家查询的情况下从查询中获取最新的 url?

//Set up artist query so only NBS artists are chose

$findartist = mysql_query("SELECT * FROM artists") or die(mysql_error());
  while ($artist = mysql_fetch_array($findartist)){

     $artist =  $artist['ID']; 

        //get track url
        $fetchurl = mysql_query("SELECT * FROM tracks WHERE id = '$artist' ORDER BY timestamp DESC LIMIT 1");

             url = mysql_fetch_array($fetchurl);
             $track_ID = $url ['ID'];
             $trackname = $url ['name'];
             $trackurl = $url ['url'];
             $artist_ID =$url['ID'];

    }

添加:

 $findartist = mysql_query("SELECT A.*, T.*
  FROM (
         SELECT T.ARTIST_ID, MIN(T.TRACK_ID) TRACK_ID
           FROM (
                    SELECT ARTIST_ID, MAX(`TIMESTAMP`) `TIMESTAMP`
                      FROM TRACKS
                  GROUP BY ARTIST_ID
                 ) L
           JOIN TRACKS T ON (    L.ARTIST_ID   = T.ARTIST_ID 
                             AND L.`TIMESTAMP` = T.`TIMESTAMP`)
       GROUP BY T.ARTIST_ID
       ) X
  JOIN ARTISTS A ON X.ARTIST_ID = A.ARTIST_ID
  JOIN TRACKS  T ON (X.TRACK_ID = T.TRACK_ID AND X.ARTIST_ID = T.ARTIST_ID)
  ORDER BY A.NAME");



             while ($artist = mysql_fetch_array($findartist)){

             $artist =  $artist['ID']; 
             $trackurl = $artist['url'];
4

3 回答 3

1

如果我对您的理解正确,您需要艺术家表中每个艺术家的最新(最新时间戳)曲目。

如果您显示您的表定义会有所帮助。我认为您在tracks表中的查询中混淆了 ARTIST_ID 和 TRACK_ID 。因此,我将始终使用列名 ARTIST_ID 和 TRACK_ID。

(TIMESTAMP 是列名的不幸选择,因为它也是 MySQL 数据类型名称,顺便说一句。没关系。)

您可以通过一个查询来完成此操作。让我们构造那个查询。这不是超级简单,但它会工作得很好。

首先,让我们获取每个艺术家的最新曲目或曲目的时间戳。这将返回一个显示 ARTISTS_ID 和最新 TIMESTAMP 的虚拟表。

   SELECT ARTIST_ID, MAX(`TIMESTAMP`) `TIMESTAMP`
     FROM TRACKS
 GROUP BY ARTIST_ID

现在,让我们将该查询嵌套到另一个查询中,以得出一个特定的 track_id,它是每个艺术家的最新曲目。有必要消除艺术家拥有多个具有完全相同时间戳的曲目的情况。在这种情况下,我们将获取编号最小的 TRACK_ID。

我想艺术家专辑中的所有曲目都有相同的时间戳,但它们的曲目 ID 是升序的,所以这会选择艺术家最新专辑中的第一首曲目。

  SELECT T.ARTIST_ID, MIN(T.TRACK_ID) TRACK_ID
    FROM (
             SELECT ARTIST_ID, MAX(`TIMESTAMP`) `TIMESTAMP`
               FROM TRACKS
           GROUP BY ARTIST_ID
          ) L
    JOIN TRACKS T ON (    L.ARTIST_ID   = T.ARTIST_ID 
                      AND L.`TIMESTAMP` = T.`TIMESTAMP`)
GROUP BY T.ARTIST_ID

看看这是怎么回事?内部子查询查找每个艺术家的最新时间戳,外部查询使用子查询查找该艺术家和时间戳的编号最小的曲目 ID。所以,现在我们有一个虚拟表,显示每个艺术家的最新 track_id。

最后,我们需要查询加入的艺人和曲目信息,以获取您的艺人列表及其最新曲目。我们将把这两个物理表与我们刚刚找到的虚拟表连接起来。

    SELECT A.*, T.*
      FROM (
             SELECT T.ARTIST_ID, MIN(T.TRACK_ID) TRACK_ID
               FROM (
                        SELECT ARTIST_ID, MAX(`TIMESTAMP`) `TIMESTAMP`
                          FROM TRACKS
                      GROUP BY ARTIST_ID
                     ) L
               JOIN TRACKS T ON (    L.ARTIST_ID   = T.ARTIST_ID 
                                 AND L.`TIMESTAMP` = T.`TIMESTAMP`)
           GROUP BY T.ARTIST_ID
           ) X
      JOIN ARTISTS A ON X.ARTIST_ID = A.ARTIST_ID
      JOIN TRACKS  T ON (X.TRACK_ID = T.TRACK_ID AND X.ARTIST_ID = T.ARTIST_ID)
  ORDER BY A.NAME

可以这样想:您有一些物理表,其中包含您的数据。您还可以创建带有子查询的虚拟表,并通过将它们嵌套在查询中来使用它们,就像它们是物理表一样。这种嵌套是它被称为结构化查询语言的原因之一。

您将需要 TIMESTAMP、ARTIST_ID 和 TRACK_ID 列上的索引才能有效地工作。

编辑: 在您的问题中确实没有足够的关于您的架构的信息来弄清楚如何明确地获取最近上传的曲目。

如果 TRACK_ID 是 TRACKS 表的自动递增主键,则很容易。获取与艺术家左连接的编号最高的曲目 ID(如果艺术家表中没有相应的行,则左连接)。

        SELECT T.*, A.*
          FROM TRACKS T
     LEFT JOIN ARTISTS A ON T.ARTIST_ID = A.ARTIST_ID
      ORDER BY T.TRACK_ID DESC
         LIMIT 1

如果 TRACK_ID 不是自动递增的主键,但您几乎没有两个时间戳相同,请执行此操作。如果恰好有两个或多个具有相同时间戳的轨道,它将任意选择其中一个。

        SELECT T.*, A.*
          FROM TRACKS T
     LEFT JOIN ARTISTS A ON T.ARTIST_ID = A.ARTIST_ID
      ORDER BY T.`TIMESTAMP` DESC
         LIMIT 1

这些数据的诀窍是要非常小心地准确指定您想要的内容。从您的问题中可以清楚地看出,您正在尝试循环获取每个艺术家的最新曲目。我的查询在您的程序中没有循环就做到了。但是,你知道吗,我不知道你所有列的名称,所以我的 SQL 可能并不完美。

于 2012-08-18T14:48:01.280 回答
1

artists表和tracks表之间的关系是one-to-many。因此,您的tracks表应该有一个列artist_id外键约束id,该约束将该列与表中的列交叉引用artists。完成后,获取最新曲目的查询将如下所示:

SELECT id, name, url, MAX(timestamp) timestamp
FROM tracks
GROUP BY artist_id
于 2012-08-18T15:02:11.953 回答
0

非常感谢@OllieJones 和@hookman 在这方面帮助我。我找到了我需要的查询,并且我在一个查询中完成了所有操作,没有任何 PHP,这要感谢他们俩。

不管怎样,它就在这里;

SELECT T.url, A.ID, T.ID
FROM tracks T
LEFT JOIN ARTISTS A ON T.ID = A.ID
WHERE T.ID = A.ID
ORDER BY T.timestamp DESC                                      
LIMIT 1

我接受了@OllieJones 的大部分查询并对其进行了一些编辑。我添加了 WHERE 子句,以便仅选择艺术家并删除 *,因此仅返回所需的数据。我还接受了@hookman 的建议并使用了大量外键。以后会帮上大忙的。

于 2012-08-18T23:23:31.230 回答