【问题标题】:How to search in an EAV table plus another MySQL如何在 EAV 表和另一个 MySQL 中搜索
【发布时间】:2014-05-14 16:24:24
【问题描述】:

我正在尝试使用 OR 语句进行查询以查找 EAV 表 keywordsdocumentstable 中的记录,但它给了我重复的结果:

SELECT d.id, d.name, d.created, d.updated 
FROM documents d 
INNER JOIN permissions p ON (d.wfid = p.wfId AND d.docid = p.docId AND p.userid = 1)
INNER JOIN keywords k0 ON (k0.document_id = d.id AND (k0.value IN('Pérez, Gabriel', 
  'DOC1') OR d.name IN ('Pérez, Gabriel', 'DOC1') ))
ORDER BY d.id DESC;

+------+------+---------------------+---------------------+
| id   | name | created             | updated             |
+------+------+---------------------+---------------------+
| 5267 | DOC1 | 2014-03-07 11:41:23 | 2014-02-25 12:39:10 |
| 5267 | DOC1 | 2014-03-07 11:41:23 | 2014-02-25 12:39:10 |
| 5267 | DOC1 | 2014-03-07 11:41:23 | 2014-02-25 12:39:10 |
| 5266 | DOC1 | 2014-03-07 11:41:23 | 2014-03-06 01:35:16 |
| 5266 | DOC1 | 2014-03-07 11:41:23 | 2014-03-06 01:35:16 |
| 5266 | DOC1 | 2014-03-07 11:41:23 | 2014-03-06 01:35:16 |
| 5265 | DOC1 | 2014-03-07 11:41:23 | 2014-02-25 12:38:37 |
| 5265 | DOC1 | 2014-03-07 11:41:23 | 2014-02-25 12:38:37 |
| 5265 | DOC1 | 2014-03-07 11:41:23 | 2014-02-25 12:38:37 |
| 5264 | DOC1 | 2014-03-07 11:41:23 | 2014-02-25 12:38:25 |
| 5264 | DOC1 | 2014-03-07 11:41:23 | 2014-02-25 12:38:25 |
| 5264 | DOC1 | 2014-03-07 11:41:23 | 2014-02-25 12:38:25 |
| 5263 | DOC1 | 2014-04-07 11:23:00 | 2014-03-20 09:54:30 |
| 5263 | DOC1 | 2014-04-07 11:23:00 | 2014-03-20 09:54:30 |
| 5263 | DOC1 | 2014-04-07 11:23:00 | 2014-03-20 09:54:30 |
+------+------+---------------------+---------------------+
15 rows in set (0.00 sec)

如果我使用SELECT DISTINCT

+------+-----------------------------+---------------------+---------------------+
| id   | name                        | created             | updated             |
+------+-----------------------------+---------------------+---------------------+
| 5355 | Documento - Digitalización  | 2014-03-31 12:57:51 | 2014-03-31 12:57:51 |
| 5354 | Documento - Digitalización  | 2014-03-28 11:14:11 | 2014-03-28 11:14:11 |
| 5267 | DOC1                        | 2014-03-07 11:41:23 | 2014-02-25 12:39:10 |
| 5266 | DOC1                        | 2014-03-07 11:41:23 | 2014-03-06 01:35:16 |
| 5265 | DOC1                        | 2014-03-07 11:41:23 | 2014-02-25 12:38:37 |
| 5264 | DOC1                        | 2014-03-07 11:41:23 | 2014-02-25 12:38:25 |
| 5263 | DOC1                        | 2014-04-07 11:23:00 | 2014-03-20 09:54:30 |
+------+-----------------------------+---------------------+---------------------+
7 rows in set (0.00 sec)

然后我得到我想要的。

我的问题是:

1) 为什么第一行重复?

2) 使用 SELECT DISTINCT 不好还是有助于提高性能?

3) 我的查询写错了吗?我需要在文档表和关键字表中搜索输入的值,以查看是否存在匹配项(如 Google 搜索)

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)

【问题讨论】:

  • 这不是因为您的查询写得不好。这是因为你的数据库结构是bad-designed
  • @AlmaDo 我知道它不好,这是我必须忍受的东西,直到我制作第二个版本,我必须维护这段代码:(
  • el Señor Peréz 是谁?为什么他的名字同时出现在名字和价值观中?
  • @OllieJones,因为在搜索中,可以输入类似谷歌的值,例如:StackOverflow MySql,因为数据可以是Document Name或Keyword Value,所以必须在两个表中都搜索

标签: mysql sql entity-attribute-value


【解决方案1】:

很难从您的问题中辨别出关键字表的确切形式,因此此答案可能不正确。

但是,通常可以像这样访问关键字(名称/值对)表,只检索一个关键字的值。

 SELECT d.id, d.name, d.created, d.updated, 
        k0.value AS doc1_value,
        k1.value AS doc2_value 
   FROM documents AS d
   LEFT JOIN keywords AS k0 ON k0.document_id = d.id AND k0.name = 'DOC1'
   LEFT JOIN keywords AS k1 ON k1.document_id = d.id AND k1.name = 'DOC2'

这将为每个文档检索名称为 DOC1 和 DOC2 的关键字属性的值。使用 LEFT JOIN 来处理特定文档可能缺少关键字值的情况。

您是否正在寻找具有包含特定值的任何属性的文档?在这种情况下,您可能需要这样做:

 SELECT d.id, d.name, d.created, d.updated, 
        k0.value AS doc1_value,
        k1.value AS doc2_value 
   FROM documents AS d
   JOIN keywords AS sk ON sk.document_id = d.id AND sk.value = 'Pérez, Gabriel'
   LEFT JOIN keywords AS k0 ON k0.document_id = d.id AND k0.name = 'DOC1'
   LEFT JOIN keywords AS k1 ON k1.document_id = d.id AND k1.name = 'DOC2'

注意使用 JOIN 而不是 LEFT JOIN 来排除不匹配的行。

【讨论】:

  • 谢谢奥利,很抱歉不是很清楚,我已经用表格描述更新了我的问题。我不会搜索keywords.name,只会搜索keywords.valuedocument.name。因此,如果我搜索 DOC1,它肯定会在 document.name 上,但由于我不知道,我必须同时查看 keywords.valuedocument.name 在简单搜索中输入的每个单词,并使用匹配
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-28
  • 1970-01-01
  • 1970-01-01
  • 2011-10-13
  • 2018-06-06
相关资源
最近更新 更多