我有两个表ITEM和CONDITION,下面有db结构
ITEM =>
ID - INTEGER
ITEM_NAME - VARCHAR
CONDITION =>
CID - INTEGER
COND_NAME - VARCHAR
ITEM_ARRAY - VARCHAR (Stores all ITEM ID's separated by space
like: 1 5 9 17 18
CID COND_NAME IEM_ARRAY
1 C1 1 5 9
2 C2 9 17 18
3 C3 3 7 11
在我在前端网站的应用程序中,我们给出了一个选项,用户可以根据我们必须短列表建议的项目选择一个或多个项目
为此,我们创建了一个ITEM_ARRAY列,用于保存由数组分隔的相关ITEMS的信息。
我需要一个查询,根据相关的CONDITION表项列出ITEM表中的所有ITEM_NAME。例如,如果用户选择1和9,那么我们必须显示ITEM ID(5 17 18)及其相应的ITEM NAME。像这样。
ID | ITEM_NAME
---+-----------
5 | SOME ITEM1
17 | SOME ITEM2
18 | SOME ITEM3
我试着写一个查询
SELECT SUBSTRING(s.ITEM,2, LENGTH(s.ITEM))
FROM ( SELECT REPLACE(ITEM_ARRAY," ",",") as ITEM
FROM `CONDITION`
WHERE ITEM like "% 1 5 %") s
上面的查询显示了CONDITION表中所有相关ITEM_ARRAY的列表,如果用户选择1和5.但如果用户选择了一些不同的值,如1,9或1,17,18种ITEMS,那么我的查询将无法列出相关项目。
我如何获得所有相关值。我们可以自由地对表结构进行一些更改而不需要数据冗余。
请提出宝贵的建议以克服这个问题。如果触发器等任何其他概念可以帮助我们,请指导我。
答案 0 :(得分:1)
我认为您最好的选择是重新设计CONDITION
表,使其在单个ITEM ARRAY中没有所有ITEM ID - 您应该为每个ITEM ID设置一行。在这种情况下,您应该稍微规范化数据,例如:
CREATE TABLE cond (
CID INT PRIMARY KEY AUTO_INCREMENT,
COND_NAME VARCHAR(128));
CREATE TABLE condition_items (
CID INT,
ITEM_ID INT);
INSERT INTO cond VALUES (1,'C1');
INSERT INTO condition_items VALUES (1,1),(1,5),(1,9);
INSERT INTO cond VALUES(2,'C2');
INSERT INTO condition_items VALUES (2,9),(2,17),(2,18);
如果您使用InnoDB,则可以使用外键来强制执行完整性:
ALTER TABLE condition_items ADD FOREIGN KEY (CID) REFERENCES cond (CID);
这将允许在表之间执行非常简单的JOIN。
SELECT item_id,item_name
FROM cond
JOIN condition_items USING (CID)
JOIN item ON (item.id=condition_items.item_id)
WHERE cond_name="C2";
请注意,您应避免使用CONDITION
作为表名,因为它是保留字。
答案 1 :(得分:0)
如果您可以更改表格结构,则应将ITEM_ARRAY
移到自己的表格中。
COND_ITEM =>
COND_ID => INTEGER (foreign key to CONDITION table)
ITEM_ID => INTEGER (foreign key to ITEM table)
然后您可以使用查询:
SELECT ID, ITEM_NAME
FROM ITEM
WHERE ID IN (
SELECT ITEM_ID
FROM COND_ITEM
WHERE COND_ID IN (
SELECT COND_ID
FROM COND_ITEM
WHERE ITEM_ID IN (1, 9)
) AND ITEM_ID NOT IN (1, 9)
)
或加入:
SELECT DISTINCT i.ID, i.ITEM_NAME
FROM ITEM AS i
JOIN COND_ITEM AS ci1 ON ci1.ITEM_ID = i.ID
JOIN COND_ITEM AS ci2 ON ci1.COND_ID = ci2.COND_ID
WHERE ci1.ITEM_ID NOT IN (1, 9)
AND ci2.ITEM_ID IN (1, 9)