2008-11-26 32 views
1

我有一个数据库有一个表,像这样新手SQL查询问题(4000个唯一用户和3000个独特的电影)的电影评级数据库

我打算对它做一个矩阵SVD(奇异值分解),所以我想把这个数据库作为一个有序数组返回。基本上,我想要按顺序返回每个用户,并且为每个用户按顺序返回每部电影,然后返回该用户,电影对的评分,或者如果该用户未对该特定电影评级,则返回null。例如:

USERID | MOVIEID | RATING 
------------------------- 
99835 8847874 4 
99835 8994385 3 
99835 9001934 null 
99835 3235524 2 
      . 
      . 
      . 
109834 8847874 null 
109834 8994385 1 
109834 9001934 null 

etc 

这样,我可以简单地将这些结果读入适合我的SVD算法的二维数组中。 (任何其他建议为获得信息的数据库到一个简单的二维浮点阵列将不胜感激)

重要的是,这是返回的顺序,以便当我得到我的二维数组时,我将能够将这些值重新映射到相应的用户和电影中进行我的分析。

回答

6
SELECT m.UserID, m.MovieID, r.Rating 
    FROM (SELECT a.userid, b.movieid 
       FROM (SELECT DISTINCT UserID FROM Ratings) AS a, 
        (SELECT DISTINCT MovieID FROM Ratings) AS b 
     ) AS m LEFT OUTER JOIN Ratings AS r 
     ON (m.MovieID = r.MovieID AND m.UserID = r.UserID) 
    ORDER BY m.UserID, m.MovieID; 

现在测试,它似乎工作!

这个概念是在Ratings表中用MovieID值列表(ouch!)在Ratings表中创建UserID值列表的笛卡尔乘积,然后将该完整矩阵的外连接与评级表(再次)收集评级值。

这是不是高效。

它可能是有效的。

尽管只是简单地选择数据,并且在数据到达时安排阵列填充,但您可能会做得更好。如果你有成千上万的用户和电影,你将会返回数百万行,但其中大多数将会有空值。您应该将传入的数据视为稀疏矩阵的描述,首先将程序中的矩阵设置为全零(或其他缺省值),然后从数据库读取流并设置实际存在的行。

该查询是基本上微不足道:

SELECT UserID, MovieID, Rating 
    FROM Ratings 
    ORDER BY UserID, MovieID; 
+0

感谢,tvanfosson,为ON子句中的编辑。 – 2008-11-26 04:15:11

0

如果我正确理解你的问题,你有你的表中的所有数据,而你只是要提取它的正确顺序。那是对的吗?如果是的话,它应该只是一个mattter:

select userid, movieid, rating 
from ratings 
order by userid, movieid 
+0

如果用户想要的是每个用户使用相同大小的“数组”,那么这将不起作用 - 他表示数据库中不存在所有userid/movieid对。您的答案为每个用户提供可变数量的记录。 – paxdiablo 2008-11-26 04:11:42

1

有时做的最好的事情是重构表/正常化您的数据(如果这是一个选项)。

规范化数据结构:

用户表:(所有的不同用户)
用户ID,名字,姓氏

影表:(所有不同的电影)
MovieId,名称

UserMovieRatings :(用户给电影的评分)
UserId,MovieId,Rating

如果您想要每个用户和电影的组合,然后根据需要使用UserMovieRatings表,则可以进行笛卡尔连接。

在系统变得更复杂之前,最好现在重做。就拿这次的前期,我敢肯定你需要自然来任何疑问...希望帮助...

示例查询:

 

select UserId, FirstName, LastName, MoveId, Name, cast(null as int) as Rating 
into #FinalResults 
from Users 
cross join Movies 
 
 

update #FinalResults 
set Rating = UMR.Rating 
from #FinalResults FR 
inner join UserMovieRatings UMR 
on FR.UserId = UMR.UserId and FR.MovieId = UMR.MovieId