需要在mysql db中查询所需的输出

时间:2014-06-26 06:32:06

标签: mysql database

我有两个表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,那么我的查询将无法列出相关项目。

我如何获得所有相关值。我们可以自由地对表结构进行一些更改而不需要数据冗余。

请提出宝贵的建议以克服这个问题。如果触发器等任何其他概念可以帮助我们,请指导我。

2 个答案:

答案 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)

DEMO