草庐IT

mysql - SQL 按首选值列表分组

coder 2023-06-12 原文

首先:我不太清楚该在问题标题中输入什么,我不知道如何调用这样的查询,也许这就是我找不到任何答案的原因。

我有一个广播电台表和一个流表。每个广播电台可以有多个流,用于不同的格式、比特率等。 我想获取所有电台的列表,以及给定应用程序首选格式的流。

现在这很棘手,我希望首选格式为列表,并且我的数据库应返回第一个合适的流。

所以我可能有一个这样的列表:('MP3', 'AAC', 'OGG')

然后我希望 MySQL 为每个站点返回“MP3”类型的流,但如果它不存在,它应该返回该站点的“AAC”流,依此类推。 如果没有找到合适的流,它不应该返回站。

示例:

CREATE TABLE `stations` (
  `id` INT(11),
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

CREATE TABLE `streams` (
  `id` INT(11),
  `station` INT(11),
  `media_type` ENUM('MP3', 'OGG', 'AAC', 'Flash'),
  PRIMARY KEY (`id`),
  KEY (`station`),
  CONSTRAINT `fk_1` FOREIGN KEY (`station`) REFERENCES `stations` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB;

INSERT INTO `stations` (`id`) VALUES (1), (2), (3);
INSERT INTO `streams` (`id`, `station`, `media_type`) VALUES (1, 1, 'MP3'), (2, 1, 'AAC'), (3, 2, 'Flash'), (4, 2, 'AAC'), (5, 3, 'Flash');

我做了一个SQLFiddle here

如果首选媒体类型列表是('MP3', 'AAC'),那么使用上面示例数据的期望结果应该是:

station stream  type
1       1       MP3
2       4       AAC
  • Station 1 应具有 MP3 类型的流 1(也支持 AAC,但 MP3 优于 AAC)
  • Station 2 应该有 AAC 类型的流 4(Station 2 不提供 MP3,但 AAC 提供)
  • Station 3 不应出现在结果中,因为它仅通过 Flash 提供流媒体

我试过了:

SELECT
    st.id AS station_id,
    str.id AS stream_id,
    str.media_type,
    FIELD(str.media_type, 'MP3', 'AAC') AS preference
FROM
    stations st
LEFT JOIN
    streams str ON str.station = st.id
GROUP BY 
    st.id
HAVING
    MIN(preference)

但是根据流表中的第一条记录是否是首选媒体类型,它只返回 1 或 0 条记录,我不明白为什么。

我能找到的唯一解决方案是使用子查询对流进行排序,然后按 station_id 分组,如下所示:

SELECT sub.* FROM
    (SELECT
        st.id AS station_id,
        str.id AS stream_id,
        str.media_type
    FROM
        stations st
    LEFT JOIN
        streams str ON str.station = st.id
    WHERE
        str.media_type IN ('MP3', 'AAC')
    ORDER BY
        FIELD(str.media_type, 'MP3', 'AAC')
    ) AS sub
GROUP BY sub.station_id

但这会导致子查询正在创建的临时表的全表扫描,性能无法接受。由于我们不能限制内部查询(因为它还没有分组),临时表会变得非常大。

顺便说一句,我正在运行 MySQL 5.6

那么,我应该使用哪种查询来处理首选属性列表?

最佳答案

如果您只想返回 'MP3''AAC' 存在的行,则不需要外连接。

这是一个标准 SQL 解决方案,可以在 mysql 中按原样工作,请参阅 fiddle :

SELECT
   st.id AS station_id,
   COALESCE(MAX(CASE WHEN str.media_type = 'MP3' THEN str.id END)
           ,MAX(CASE WHEN str.media_type = 'AAC' THEN str.id END)
           ) AS stream_id,
   COALESCE(MAX(CASE WHEN str.media_type = 'MP3' THEN str.media_type END)
           ,MAX(CASE WHEN str.media_type = 'AAC' THEN str.media_type END)
           ) AS media_type
FROM stations st
JOIN streams str 
  ON str.station = st.id
WHERE -- only stations with the requested media types
   str.media_type IN ('MP3', 'AAC')
GROUP BY st.id

添加更多媒体类型很容易,主要是剪切和粘贴。 COALESCE 根据 CASE 的顺序返回第一个匹配的媒体类型。

关于mysql - SQL 按首选值列表分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32080957/

有关mysql - SQL 按首选值列表分组的更多相关文章

  1. ruby-on-rails - 按天对 Mongoid 对象进行分组 - 2

    在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev

  2. ruby - RVM 使用列表[0] - 2

    是否有类似“RVMuse1”或“RVMuselist[0]”之类的内容而不是键入整个版本号。在任何时候,我们都会看到一个可能包含5个或更多ruby的列表,我们可以轻松地键入一个数字而不是X.X.X。这也有助于rvmgemset。 最佳答案 这在RVM2.0中是可能的=>https://docs.google.com/document/d/1xW9GeEpLOWPcddDg_hOPvK4oeLxJmU3Q5FiCNT7nTAc/edit?usp=sharing-知道链接的任何人都可以发表评论

  3. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

  4. Hive SQL 五大经典面试题 - 2

    目录第1题连续问题分析:解法:第2题分组问题分析:解法:第3题间隔连续问题分析:解法:第4题打折日期交叉问题分析:解法:第5题同时在线问题分析:解法:第1题连续问题如下数据为蚂蚁森林中用户领取的减少碳排放量iddtlowcarbon10012021-12-1212310022021-12-124510012021-12-134310012021-12-134510012021-12-132310022021-12-144510012021-12-1423010022021-12-154510012021-12-1523.......找出连续3天及以上减少碳排放量在100以上的用户分析:遇到这类

  5. ruby - 在 Ruby 中创建按公共(public)键值分组的新哈希 - 2

    假设我有一个在Ruby中看起来像这样的哈希:{:ie0=>"Hi",:ex0=>"Hey",:eg0=>"Howdy",:ie1=>"Hello",:ex1=>"Greetings",:eg1=>"Goodday"}有什么好的方法可以将它变成如下内容:{"0"=>{"ie"=>"Hi","ex"=>"Hey","eg"=>"Howdy"},"1"=>{"ie"=>"Hello","ex"=>"Greetings","eg"=>"Goodday"}} 最佳答案 您要求一个好的方法来做到这一点,所以答案是:一种您或同事可以在六个月后理解

  6. sql - 查询忽略时间戳日期的时间范围 - 2

    我正在尝试查询我的Rails数据库(Postgres)中的购买表,我想查询时间范围。例如,我想知道在所有日期的下午2点到3点之间进行了多少次购买。此表中有一个created_at列,但我不知道如何在不搜索特定日期的情况下完成此操作。我试过:Purchases.where("created_atBETWEEN?and?",Time.now-1.hour,Time.now)但这最终只会搜索今天与那些时间的日期。 最佳答案 您需要使用PostgreSQL'sdate_part/extractfunction从created_at中提取小时

  7. ruby - Watir 更改 Mozilla Firefox 首选项 - 2

    我正在使用Watir运行一个Ruby脚本来为我自动化一些事情。我试图自动将一些文件保存到某个目录。因此,在我的Mozilla设置中,我将默认下载目录设置为桌面并选择自动保存文件。但是,当我开始运行我的脚本时,这些更改并没有反射(reflect)出来。似乎首选项恢复为默认值。我已经包括以下内容require"rubygems"#Optional.require"watir-webdriver"#Forwebautomation.require"win32ole"#Forfilesavedialog.并打开一个新的firefox实例:browser=Watir::Browser.new(:

  8. Ruby on Rails regexp equals-tilde 与 array include 用于检查选项列表 - 2

    我正在使用Rails3.2.3和Ruby1.9.3p0。我发现我经常需要确定某个字符串是否出现在选项列表中。看来我可以使用Ruby数组.includemethod:或正则表达式equals-tildematchshorthand用竖线分隔选项:就性能而言,一个比另一个好吗?还有更好的方法吗? 最佳答案 总结:Array#include?包含String元素,在接受和拒绝输入时均胜出,对于您的示例只有三个可接受的值。对于要检查的更大的集合,看起来Set#include?和String元素可能会获胜。如何测试我们应该根据经验对此进行测试

  9. ruby-on-rails - 无法安装 mysql2 0.3.14 gem - 2

    我看到其他人也遇到过类似的问题,但没有一个解决方案对我有用。0.3.14gem与其他gem文件一起存在。我已经完全按照此处指示完成了所有操作:https://github.com/brianmario/mysql2.我仍然得到以下信息。我不知道为什么安装程序指示它找不到include目录,因为我已经检查过它存在。thread.h文件存在,但不在ruby​​目录中。相反,它在这里:C:\RailsInstaller\DevKit\lib\perl5\5.8\msys\CORE\我正在运行Windows7并尝试在Aptana3中构建我的Rails项目。我的Ruby是1.9.3。$gemin

  10. ruby - 如何使用 ruby​​ mysql2 执行事务 - 2

    我已经开始使用mysql2gem。我试图弄清楚一些基本的事情——其中之一是如何明确地执行事务(对于批处理操作,比如多个INSERT/UPDATE查询)。在旧的ruby-mysql中,这是我的方法:client=Mysql.real_connect(...)inserts=["INSERTINTO...","UPDATE..WHEREid=..",#etc]client.autocommit(false)inserts.eachdo|ins|beginclient.query(ins)rescue#handleerrorsorabortentirelyendendclient.commi

随机推荐