【问题标题】:SQL Join two tables and select a matching record at random from the second tableSQL连接两张表,从第二张表中随机选择一条匹配的记录
【发布时间】:2014-01-04 18:21:03
【问题描述】:

我有两个表,一个用户表和一个 MyPhotos 表。 UserTable 包含一个 UserID 列和其他与用户信息有关的列。 MyPhotos 表包含 UserID 和 ImageFile 列。

MyPhotos 表可以为单个 UserID 包含多个记录。我需要一种方法来查找特定用户的照片总数,以及为每个用户 ID随机选择的 ONE 图像文件。

我当前使用的 SQL 语句每次都返回相同的图像,而不是随机图像。这里是:

SELECT  MyPhotos.UserID, 
        UsrTbl.ScreenName, COUNT(*) AS TotalPhotos, 
        MAX(MyPhotos.ImagesFileName) AS Expr1
FROM MyPhotos 
INNER JOIN UsrTbl ON MyPhotos.UserID = UsrTbl.AccountID
GROUP BY MyPhotos.UserID, UsrTbl.ScreenName
ORDER BY NEWID()

非常感谢任何帮助!

谢谢!

【问题讨论】:

    标签: sql sql-server


    【解决方案1】:

    我通常喜欢在 tempdb 中设置几个测试表,以便您可以尝试解决方案。我没有在设计中添加任何完整性,因为你有真正的桌子。

    -- Just playing
    use Tempdb;
    Go
    
    --
    -- Table 1
    --
    
    -- Remove table
    if OBJECT_ID('MyPhotos') > 0
    drop table MyPhotos
    go
    
    -- Simple photo table
    create table MyPhotos
    (
    UserID int,
    ImagesFileName varchar(64)
    );
    
    -- Some data
    insert into MyPhotos values
    (1, 'c:\pics\fee.jpg'),
    (1, 'c:\pics\fi.jpg'),
    (1, 'c:\pics\foo.jpg'),
    (1, 'c:\pics\fumb.jpg'),
    (2, 'c:\pics\huff.jpg'),
    (2, 'c:\pics\n.jpg'),
    (2, 'c:\pics\puff.jpg');
    
    -- Show the data
    select * from MyPhotos
    
    
    --
    -- Table 2
    --
    
    -- Remove table
    if OBJECT_ID('UsrTbl') > 0
    drop table UsrTbl
    go
    
    -- Simple photo table
    create table UsrTbl
    (
    AccountID int,
    ScreenName varchar(64)
    );
    
    -- Some data
    insert into UsrTbl values
    (1, 'Jolly Green Giant'),
    (2, 'Big Bad Wolf');
    
    -- Show the data
    select * from UsrTbl;
    

    解决问题的一种方法是使用公用表表达式。

    --
    -- Grab a random pic by user id
    -- 
    
    ;
    WITH ctePhotos 
    as
    (
        SELECT 
          UserID, ImagesFileName, 
          ROW_NUMBER() OVER (PARTITION BY UserID ORDER BY UserID) as ImgNo
        FROM 
          MyPhotos 
    ),
    cteRandomPick
    AS
    (
        SELECT UserID, CEILING(RAND() * MAX(ImgNo)) AS ImgNo
        FROM ctePhotos
        GROUP BY UserId
    )
    SELECT 
      p.UserId,
      u.ScreenName,
      p.ImgNo,
      p.ImagesFileName
    FROM UsrTbl as u INNER JOIN ctePhotos as p ON u.AccountID = p.UserID
    INNER JOIN cteRandomPick as r ON p.UserID = r.UserID and p.ImgNo = r.ImgNo;
    

    ctePhones 只是通过用户 ID 枚举图片、图片编号。 cteRandomPick 抓取最大值 图片编号并乘以 RAND() 函数得到一张随机图片。

    最后但并非最不重要的一点是,body 将两个 CTE 和 User Table 连接起来以获得您的结果。

    如果你多次运行代码,你会得到不同的选择。

    【讨论】:

    • +1 我使用您的 DDL+INSERT 脚本来测试我的解决方案。谢谢。
    • 很酷,非常感谢。我添加了 SELECT UserID, CEILING(RAND() * MAX(ImgNo)) AS ImgNo, COUNT(*) AS TotalPhotos 以获取用户提交的照片总数。显示用户提交的总照片以及为该用户随机选择的图像的数据列表的完美解决方案。
    猜你喜欢
    • 2011-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-23
    • 1970-01-01
    • 1970-01-01
    • 2012-03-01
    • 1970-01-01
    相关资源
    最近更新 更多