【问题标题】:SQLite: Total Column value and then compare to inputSQLite:总列值,然后与输入进行比较
【发布时间】:2018-04-05 19:49:44
【问题描述】:

在我的测试程序中,用户输入他们希望播放列表的总时间,然后它会生成一个不再是给定时间的播放列表。 但是,我遇到了一些问题,因为我不知道如何计算播放列表中歌曲的总长度,然后确保查询不再是给定的时间。请有人可以帮助我吗? 这是我的代码:

c.execute ('SELECT (TOTAL(Length) AS TotalSongLength, "Song Name", "Artist", "Genre", "Album", "Year") FROM Songs WHERE TotalSongLength <= "{0}"'.format(TotalSongLengthInput))

在代码之前发生的所有事情都是用户输入时间限制。在表中,歌曲存储为MM:SS 格式,它们的输入会自动转换为该格式。我只是在为上述问题苦苦挣扎^。

【问题讨论】:

    标签: python sql python-3.x sqlite


    【解决方案1】:

    你可以使用 sum 和 group by

    为了过滤你应该使用的结果(对于聚合结果)而不是在哪里

     SELECT sum(Length) AS TotalSongLength, "Song Name", "Artist", "Genre", "Album", "Year" 
     FROM Songs 
     GROUP BY "Song Name", "Artist", "Genre", "Album", "Year" 
     HAVING TotalSongLength <= "{0}"'
    

    【讨论】:

    • 好的,这会很好,但是,因为歌曲的格式存储为MM:SS 它不起作用。有没有办法让它将MM:SS 转换为秒,然后使 SUM(Length[In Seconds])
    • 嘿,我又听了@Jeremy 所说的,而是将每首歌曲转换为秒数(作为新列:LengthSeconds),所以理论上,你的代码应该 i> 工作,但是,它仍然让我超过 600 秒(10 分钟)的歌曲。 ://
    【解决方案2】:

    我认为以下可能适合:-

    SELECT 
        CASE 
            WHEN seconds > 0 AND seconds < 300 
            THEN 'Playlist OK' 
            ELSE 'Playlist too long or not long enough' 
        END AS result
    FROM 
        (SELECT sum((substr(length,1,2) * 60) + substr(length,4,2)) as seconds 
        FROM songs);
    
    • 其中 300 是允许的总时间。

    测试

    这是使用以下方法测试的:-

    DROP TABLE IF EXISTS songs;
    CREATE TABLE IF NOT EXISTS songs ("Song Name" TEXT,"Artist" TEXT, "Genre" TEXT, "Album" TEXT, "Year", length TEXT);
    INSERT INTO songs VALUES ('My Song','Fred','Rock','Fred Rocks','1974', '03:11');
    INSERT INTO songs VALUES ('Another Song','Bert','Pop','Bert sings','2010', '02:59');
    SELECT 
        CASE WHEN seconds > 0 AND seconds < 300 THEN 'Playlist OK' ELSE 'Playlist too long or not long enough' END AS result
    
    FROM (SELECT sum((substr(length,1,2) * 60) + substr(length,4,2)) as seconds FROM songs)
    

    然后:-

    • a) 注释掉所有插入(歌曲),
    • b) 注释掉第一首歌,
    • c) 注释掉第二首歌和
    • d) 不评论任何歌曲

    测试结果

    • a) 播放列表太长或不够长
    • b) 播放列表正常
    • c) 播放列表正常
    • d) 播放列表太长或不够长

    如果您还想要以秒为单位的时间,那么:-

    SELECT seconds,
        CASE 
            WHEN seconds > 0 AND seconds < 300 
            THEN 'Playlist OK' 
            ELSE 'Playlist too long or not long enough' 
        END AS result
    FROM 
        (SELECT sum((substr(length,1,2) * 60) + substr(length,4,2)) as seconds FROM songs);
    
    • 请注意,如果没有行,则 seconds 将为 null 而不是 0。

    重新评论:-

    这不是我想要的。而不是说如果 播放列表低于某个时间或其他什么。我希望它显示所有 可以加在一起的歌曲,无需经过用户输入

    我相信以下会做到这一点(最后一行的 1000 是时间限制):-

    SELECT * 
    FROM 
    (
        SELECT SUM(a.seconds) AS summed, 
            b."Song Name", 
            b."Artist", 
            b."Genre", 
            b."Album", 
            b."Year", 
            b.length, 
            b.seconds 
        FROM  (
            SELECT *,
                (substr(length,1,2) * 60) + substr(length,4,2) AS seconds 
            FROM songs ORDER BY length) AS a,
        (
            SELECT *,
                (substr(length,1,2) * 60) + substr(length,4,2) AS seconds 
            FROM songs ORDER BY length) AS b 
        WHERE b."Song Name" <= a."Song Name"
        GROUP BY b."Song Name" ORDER BY summed
    ) 
    WHERE summed <= 1000
    

    根据表格:-

    运行上述结果:-

    限制 = 1000 :-

    限制 = 10000 :-

    限制 = 600 :-

    【讨论】:

    • 嗨。感谢您抽出宝贵的时间将其全部写出来并为我进行测试。该代码确实有效,但是,它并不是我想要的。而不是说播放列表是否低于某个时间或其他。我希望它显示所有可以添加在一起的歌曲,而不需要经过用户输入。
    • @JamesSmith 用可能的解决方案编辑了答案
    • P.S 这不是最有效的解决方案,而且可能会占用大量资源,因为要处理的行数是表中的行数 * 表中的行数。
    • 好的,效果很好!非常感谢您抽出宝贵时间来帮助我。
    【解决方案3】:

    还不能回复 cmets,但 scaisEdge 可以为您提供所需的答案

    表格上的数据类型将迫使您将所看到的所有内容转换为秒,如下所示:

     SELECT 
           SongName
         , strftime('%MM', Length) * 60 + strftime('%SS',Length) AS TotalSeconds
         , Length
     FROM Songs 
     GROUP BY SongName, Length
     HAVING TotalSeconds <= "{0}" 
    

    然后您还必须将用户输入解析为秒数以与 TotalSeconds 进行比较

    【讨论】:

    • 嗨,请阅读我发送给@scaisEdge 评论的评论。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多