我有一个关于一般数据库结构的SQL相关问题似乎有些常见。有一天我试图解决一个问题,然后(后来)我看到其他人做了同样的事情(或者非常相似的事情),所以我认为结构本身是有意义的。我只是在尝试对它形成某些查询时遇到了麻烦。
这个想法是你有一个包含“items”的表,你想为每个项目存储一组字段及其值。通常这可以通过简单地向items表添加列来完成,问题是字段本身(不仅仅是值)因项目而异。例如,我可能有两个项目:
第1条
product_id = aproductid
hidden_key = ahiddenkeyvalue
第2条
product_id = anotherproductid
地址= anaddress
您可以看到两个项目都有product_id字段(具有不同的值),但每个项目存储的数据不同。
数据库中的结构最终会是这样的:
ItemsTable
ID
itemdata_1
itemdata_2
...
FieldsTable
ID
FIELD_NAME
...
与他们相关并使其有效的表格
FieldsItemRelationsTable
FIELD_ID
ITEM_ID
值
<小时/> 好吧,当我尝试做一些只涉及一个“动态场”值的事情时,没有问题。我通常做类似的事情:
SELECT i.* FROM ItemsTable i
INNER JOIN FieldsItemRelationsTable v ON v.item_id = i.id
INNER JOIN FieldsTable f ON f.id = v.field_id
WHERE v.value = 50 AND f.name = 'product_id';
选择product_id = 50
的所有项目当我需要做一些涉及多个“动态字段”值的事情时,会出现问题。假设我想选择product_id = 50 AND hidden_key = 30的所有项目。是否可以使用单个SQL语句?我试过了:
SELECT i.* FROM ItemsTable i
INNER JOIN FieldsItemRelationsTable v ON v.item_id = i.id
INNER JOIN FieldsTable f ON f.id = v.field_id
WHERE (v.value = 50 AND f.name = 'product_id')
AND (v.value = 30 AND f.name = 'hidden_key');
但它只返回零行。
答案 0 :(得分:2)
您需要为要带回的每个值单独加入...
SELECT i.* FROM ItemsTable i
INNER JOIN FieldsItemRelationsTable v ON v.item_id = i.id
INNER JOIN FieldsTable f ON f.id = v.field_id
INNER JOIN FieldsItemRelationsTable v2 ON v2.item_id = i.id
INNER JOIN FieldsTable f2 ON f2.id = v2.field_id
WHERE v.value = 50 AND f.name = 'product_id'
AND (v2.value = 30 AND f2.name = 'hidden_key');
呃...那个查询可能无法运行(我的部分复制/粘贴污泥工作),但你明白了......你需要在表的第二个实例中保存的第二个值(s)(我的例子中的v2和f2)与第一个实例分开。 v1.value = 30和v2.value = 50. v1.value = 50和v1.value = 30永远不应该返回行,因为没有任何东西同时等于30和50
作为一个想法...如果你把where子句放在join语句
中,查询可能会更容易阅读SELECT i.* FROM ItemsTable i
INNER JOIN FieldsItemRelationsTable v ON v.item_id = i.id and v.value = 50
INNER JOIN FieldsTable f ON f.id = v.field_id and f.name = 'product_id'
INNER JOIN FieldsItemRelationsTable v2 ON v2.item_id = i.id and v2.value = 30
INNER JOIN FieldsTable f2 ON f2.id = v2.field_id and f2.name = 'hidden_key'
在功能上,两个查询都应该运行相同。我不确定是否存在逻辑限制......在调度系统中,您经常会看到“异常”的设置...我有一个报告查询,这样加入了28次...每个例外一个返回类型。
答案 1 :(得分:1)
答案 2 :(得分:0)
尝试做一些左或右连接,看看你是否得到任何结果。如果有空字段,内部联接有时不会返回结果。
这是一个开始。不要忘了,外连接=笛卡儿产品