快速SQL搜索和排序没有临时表

时间:2013-12-24 19:51:08

标签: mysql sql select group-by sql-order-by

我有两张桌子。

TAB1:

+------------+
| id | title |
+------------+
| 1 | B      |
| 2 | C      |
| 3 | A      |
| 4 | A      |
| 5 | A      |
| 6 | A      |
| ...        |
+------------+

PK:身份证 索引:标题

TAB2:

+-------------------------------------------+
| id | item_id | item_key |     item_value  |
+-------------------------------------------+
| 1  | 1       | value    | $4              |
| 2  | 1       | url      | http://h.com/   |
| 3  | 2       | value    | $5              |
| 4  | 3       | url      | http://i.com/   |
| 5  | 3       | value    | $1              |
| 6  | 3       | url      | http://y.com/   |
| 7  | 4       | value    | $2              |
| 8  | 4       | url      | http://z.com/   |
| 9  | 5       | value    | $1              |
| 10 | 5       | url      | http://123.com/ |
| ...                                       |
+-------------------------------------------+

PK:id 索引:item_id,item_key

  • item_id是tab1中的外键。

我如何制作它,以便根据两个表中的条件按顺序从Tab1获取一个id表。标准如下:

  • 按标题订购ASC。如果标题相同,
  • 按值排序DESC。如果标题和值都相同,
  • 优先考虑'url'键包含'123.com'的项目。

带有有序结果的结果表将是:

+------------+
| id | title |
+------------+
| 4 | A      |
| 5 | A      |
| 3 | A      |
| 6 | A      |
| 1 | B      |
| 2 | C      |
| ...        |
+------------+

我知道我可以用:

SELECT Tab1.id, Tab1.title
FROM Tab1
JOIN Tab2 t2_val ON t2_val.item_id = Tab1.id AND t2_val.item_key='value'
JOIN Tab2 t2_url ON t2_url.item_id = Tab1.id AND t2_url.item_key='url'
ORDER BY title, 
         t2_val.item_value DESC,
         t2_url.item_value LIKE '%123.com%' DESC

但是对于大型数据集来说,它太慢了。有没有办法更快地做到这一点?我在选项卡1中设置了id和title的索引,在选项卡2中设置了项目键。现在我想删除临时表,如果可以的话,这意味着没有连接,对吧?

如何做到这一点?

2 个答案:

答案 0 :(得分:0)

首先,对于较大的数据集,结果集会更大。你之后对数据做了什么?性能下降主要与数据库中的数据有关,而与数据库中的处理无关。

接下来,你有什么指数?查询似乎是要求tab2(item_key, item_id)上的索引来解析连接。

最后,我不知道如何绕过order by的最终排序,因为它使用了两个表中的值。

您正在使用“实体 - 属性 - 值”(EAV)模型。在为大量记录选择大量列时,这本身就很慢。如果您知道自己拥有这两个字段,请考虑更改数据模型,因此urlvaluetab1中的列。

答案 1 :(得分:0)

试试这个:

SELECT t1.id, t1.title
FROM Tab1 t1
INNER JOIN (SELECT item_id, MAX(item_key='value', item_value, '') AS 'value', 
                   MAX(item_key='url', item_value, '') AS 'url'
            FROM Tab2 GROUP BY item_id
           ) t2 ON t2.item_id = t1.id
ORDER BY t1.title, t2.value DESC, IF(t2.url LIKE '%123.com%', 0, 1);