【问题标题】:How can I 'order by' non normalized column? And composite order by如何“按”非规范化列排序?和复合顺序
【发布时间】:2014-02-25 12:27:23
【问题描述】:

我有桌子documents 桌子keywords。每个文档可以有任意数量的关键字。

关键字示例:

Client Name, Billing period, Client Address

需要注意的是,文档上可以有任何关键字,所以不能规范化(它只是元数据)。

现在我想订购,例如先通过Client Name,然后再通过Billing Period,我该怎么做?

如果我制作Select * from Keywords group by keyword order by value,我就得不到我需要的东西。我对 MySQL 没有太多经验,所以我不能做更多。

测试数据示例:

+-------+-------------+----------------------+----------------------+
| id    | document_id | keyword              | value                |
+-------+-------------+----------------------+----------------------+
|   265 |          89 | Nº de Operacion     | 000534556315         |
| 15708 |        5234 | Direccion IP         | 192.168.100.168      |
|   267 |          89 | Fecha                | 20131021             |
| 15760 |        5240 | Nombre de Cliente    | CLIENTEN1            |
| 15761 |        5240 | Asunto               | DEMANDACESTADO1220   |
| 15703 |        5234 |                      | DEMANDACESTADO1220   |
| 15700 |        5234 | Nombre de Legajo     | Documento            |
| 15702 |        5234 | Nombre del Documento | Documento            |
| 15701 |        5234 | Tipo de Documento    | Documento            |
| 15842 |        5256 | Descripcion          | ffff                 |
| 15709 |        5234 | Localizacion         | No definida          |
| 15707 |        5234 | Grupo Usuario        | Operadores           |
|   266 |          89 | Socio                | Socio1               |
| 15835 |        5255 | Decripcion           | sadsdf               |
| 15704 |        5234 | ID de Usuario        | ssadmin              |
| 15706 |        5234 | Nombre de Usuario    | ssadmin              |
+-------+-------------+----------------------+----------------------+

表格

mysql> describe documents;
+---------+-----------+------+-----+---------------------+-----------------------------+
| Field   | Type      | Null | Key | Default             | Extra                       |
+---------+-----------+------+-----+---------------------+-----------------------------+
| id      | int(11)   | NO   | PRI | NULL                | auto_increment              |
| name    | char(100) | YES  |     | NULL                |                             |
| wfid    | char(50)  | YES  |     | NULL                |                             |
| docid   | char(50)  | YES  |     | NULL                |                             |
| created | timestamp | NO   |     | 0000-00-00 00:00:00 |                             |
| updated | timestamp | NO   |     | CURRENT_TIMESTAMP   | on update CURRENT_TIMESTAMP |
+---------+-----------+------+-----+---------------------+-----------------------------+
6 rows in set (0.00 sec)

mysql> describe keywords;
+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| id          | int(11)      | NO   | PRI | NULL    | auto_increment |
| document_id | int(11)      | NO   | MUL | NULL    |                |
| keyword     | char(50)     | NO   |     | NULL    |                |
| value       | varchar(250) | YES  |     | NULL    |                |
+-------------+--------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

【问题讨论】:

  • 您从显示的查询中得到什么? Select * from Keywords group by keyword order by value 。如果你把它完整地写在你的问题中会更好。
  • 据我了解,OP 要求按值动态排序(来自keywords.keyword)
  • 您的结构是众所周知的 EAV。在关系数据库的上下文中,绝大多数情况下这是一个糟糕的选择。原因我已经描述了here
  • @AlmaDo 在这种情况下你会建议做什么?文档不是固定的元数据,它们可以根据需要具有其他键值对。

标签: mysql sql


【解决方案1】:

您的“关键字”不是关键字。它们是属性值对。这种数据存储方式称为“Entity-Attribute-Value”(简称 EAV)。我不建议将它用于每个文档上的属性。

无论如何,这就是你所拥有的。您可以使用聚合和条件聚合来做您想做的事情:

select document_id,
       max(case when keyword = 'Client Name' then value end) as ClientName,
       max(case when keyword = 'Billing Period' then value end) as BillingPeriod
from keywords
group by document_id
order by ClientName, BillingPeriod;

【讨论】:

    【解决方案2】:

    尚不清楚您是否可以为每个文档拥有多个客户名称和/或多个计费周期。如果你这样做了,那么以下将实现你想要的。然而,正如其他人所说,这是在数据库中存储结构化信息的一种非常糟糕的方式。

    select d.id, cn.ClientName, bp.BillingPeriod from documents d
    left join (select document_id, value as ClientName from keywords where keyword = 'Client Name') cn on d.id = cn.document_id
    left join (select document_id, value as BillingPeriod from keywords where keyword = 'Billing Period') bp on d.id = bp.document_id
    group by name, cn.ClientName, bp.BillingPeriod, d.id
    order by cn.ClientName, bp.BillingPeriod
    

    【讨论】:

    • 您好,文档将只有一个键,例如“客户名称”,每个文档的键不会重复。
    • 那么我建议您通过在关键字表中的 document_id + 关键字上放置唯一索引来强制执行此操作
    猜你喜欢
    • 2020-06-13
    • 2020-01-08
    • 2015-03-30
    • 2013-02-15
    • 1970-01-01
    • 1970-01-01
    • 2013-02-05
    • 1970-01-01
    • 2015-12-09
    相关资源
    最近更新 更多