我有一个mysql语句,用于查询数据库中的最新曲目。但是,由于数据库部分规范化,因此ID位于不同的表中。在查询中,我从艺术家表中获取艺术家ID,并将它们放入变量中。然后将变量解析为查看轨道以查找最新轨道的查询,这就是问题所在。由于$ artist变量可以有大量的ID,所以这些ID都被解析为查询,结果是几个url放在一起,即使我已经对查询设置了LIMIT。
请记住,我无法限制艺术家的查询,因为我需要从表中获取所有艺术家,并找到所有艺术家的最新曲目。
如何在不限制艺术家查询的情况下从查询中获取最新的网址?
//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'];
答案 0 :(得分: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可能不完美。
答案 1 :(得分:1)
artists
表和tracks
表之间的关系是one-to-many
。因此,您的tracks
表格应该有一列artist_id
和foreign key constraint,可以在id
表格中使用artists
列交叉引用此列。完成此操作后,获取最新曲目的查询将如下所示:
SELECT id, name, url, MAX(timestamp) timestamp
FROM tracks
GROUP BY artist_id
答案 2 :(得分: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的建议并使用了一堆外键。将来会有很多帮助。