在SQL中选择具有最小值(计算秩)且按不同列分组的行时,性能不佳

在SQL中选择具有最小值(计算秩)且按不同列分组的行时,性能不佳,sql,performance,sqlite,group-by,min,Sql,Performance,Sqlite,Group By,Min,我的问题看起来很像这个:,但我有一些具体的问题 假设我们有这样的表: | title_id | title | type_id | crit_id | +----------+----------+---------+---------+ | 1 | title_A1 | 0 | 1111 | | 2 | title_A2 | 1 | 1111 | | 3 | title_B1 | 50 | 222

我的问题看起来很像这个:,但我有一些具体的问题

假设我们有这样的表:

| title_id |  title   | type_id | crit_id |
+----------+----------+---------+---------+
|    1     | title_A1 |     0   |   1111  |
|    2     | title_A2 |     1   |   1111  |
|    3     | title_B1 |    50   |   2222  |  
|    4     | title_B2 |    50   |   2222  |
|    5     | title_C1 |    72   |   3333  |
|    6     | title_C2 |     1   |   3333  |
|    7     | title_C4 |     0   |   3333  |
“title_id”是唯一的,并已编制索引,“title”和“crit_id”已编制索引

因此,我只希望有按“crit_id”分组的行,保存在type_id上计算的自定义秩(优先级)的最小值。 对于e.q.\U id类型的排名如下所示:

type_id = 0 - rank = 10
type_id = 50 -rank = 11
type_id = 1 - rank = 15
type_id = 72- rank = 35
etc...
最后,所有的东西都应该按“标题”的字母顺序排列 根据要求,结果应为:

| title_id |  title   | type_id | crit_id | rank |
+----------+----------+---------+---------+------+
|     1    | title_A1 |    0    |  1111   |  10  | 
|     3    | title_B1 |   50    |  2222   |  11  |
|     7    | title_C4 |    0    |  3333   |  10  |
我正在使用SQLITE。我可以通过查询获得所需的结果:

SELECT *, MIN(CASE WHEN type_id = 0 THEN 10
                   WHEN type_id = 1 THEN 11
                   WHEN type_id = 50 THEN 15
                   WHEN type_id = 72 THEN 35
                   ELSE 1000 END) as rank
FROM titles WHERE ... GROUP BY crit_id ORDER BY title
这个查询的性能非常差。在1000000条记录上,它执行时间超过10秒

这里有两个问题:

  • 我们大约有60%的记录的类型为_id==0。在这种情况下,我们执行MIN和case条款的次数约为60万次。由于排名是计算出来的,我们不能在这里使用索引。我想知道如何最大限度地减少它的执行
  • 在如此大量的数据上使用GROUPBY会带来非常糟糕的性能。阅读之后,我不确定它是否总是有正确的行为。希望有另一种方法可以做类似的事情
  • 附言: 我在嵌入式设备上运行这个程序,内存卡速度很慢,所以访问数据库的速度很慢

    我不是SQL专家,所以如果有任何解决方案,我将不胜感激。 提前谢谢


    忘了提一下,我们可以限制应该返回的结果的数量。对于e.q.
    LIMIT 500

    也许您可以利用
    (type\u id,crit\u id)
    上的复合索引,通过使用
    union all
    拆分查询:

    select crit_id, min(rank) from (
       select distinct crit_id, 10 as rank
       from titles where type_id = 0
       union all
       select distinct crit_id, 11
       from titles where type_id = 1
       union all
       select distinct crit_id, 15
       from titles where type_id = 50
       union all
       select distinct crit_id, 35
       from titles where type_id = 72
       union all
       select distinct crit_id, 1000
       from titles where type_id not in (0,1,50,72)
    ) t group by crit_id
    

    select*
    with
    groupby
    几乎从来没有做过作者想要做的事情。typeid映射是否要在表中排序?尝试以下几点:(1)使用另一种
    CASE
    语法,首先指定要测试的值,然后使用不同的
    WHEN
    子句,然后(2)将
    MIN
    函数移动到
    CASE
    中,以便获得:
    CASE MIN(type_id)当0时,然后当10时…
    当同一
    crit_id
    值存在不同值时,
    title_id
    和其他列应该给出什么?在SQL标准中(默认情况下应用于MySql 5.7),您需要以某种方式聚合
    title\u id
    (例如
    min(title\u id)
    ),或者根据它进行分组。对于不是由
    crit\u id
    功能决定的其他列也是如此。此外,在10秒内从存储卡查询嵌入式设备上的1MM记录听起来并不“非常糟糕”。如果I/O或CPU是您的瓶颈,那么更改查询可能没有多大帮助。