1

我有一个这样的 MySql 表:

ID  Category    Value
A   LOCATION    COPENHAGEN
A   LOCATION    MADRID
B   LOCATION    MADRID
C   LOCATION    MADRID
C   LOCATION    AARHUS
C   POSITION    WEBDESIGN
D   POSITION    SYSADMIN
D   POSITION    WEBDESIGN
A   GENDER      MALE
B   GENDER      MALE
C   GENDER      FEMALE

Id、Category 和 Values 共同构成了键。请注意,它们是动态的(用户定义的)并且表会很大。

现在我想得到所有ID符合某些标准的东西。要返回,ID匹配每个 中的一个值就足够了Category

例如:

给我所有拥有的 IDS

((位置 = 哥本哈根或位置 = 马德里)和(性别 = 男性))

应该返回 A, B

另一个例子:

给我所有拥有的 IDS

((POSITION = SYSADMIN OR POSITION = WEBDESIGN) AND (GENDER = FEMALE) AND (LOCATION = COPENHAGEN OR LOCATION = MADRID)) 

应该返回 C

返回的 id 将用作另一个查询的子查询 - 所以性能很重要。

更新

我用示例数据和建议的不工作解决方案创建了这个sql fiddle 。

4

2 回答 2

2

[删除了初始响应,因为它不起作用。为了使其发挥作用,我在第二次编辑中提出了更可取的查询。]


编辑

您似乎正在尝试创建一个模式来跟踪在不同位置工作的人员,并且从您的数据来看,他们似乎可能在不同的办公室中拥有多个头衔。下面的模式将允许您只定义每个人、工作和位置一次,然后使用链接表将它们连接起来。

TABLE People
  p_id INT AI PK
  p_name VARCHAR
  p_sex BOOL
  ...

TABLE Offices
  o_ID INT AI PK
  o_name VARCHAR
  o_location VARCHAR
  ...

TABLE Jobs
  j_ID INT AI PK
  j_name VARCHAR
  ...

TABLE People_Jobs_Offices  --linking table
  p_ID INT PK
  o_ID INT PK
  j_ID INT PK

现在获取马德里或哥本哈根的所有系统管理员:

SELECT *
FROM People_Jobs_Offices pjo
  INNER JOIN People p
    ON pjo.p_id = p.p_id 
  INNER JOIN Jobs j
    on pjo.j_id = j.j_id
  INNER JOIN Offices o
    ON pjo.o_id = o.o_id
WHERE
  j.j_name = 'SYSADMIN'
  AND ( o.o_location = 'MADRID'
    OR o.o_location = 'COPENHAGEN' )

这种方法称为数据库规范化,通常可以充分利用任何 RDBMS 中的索引,并通过避免数据重复将表中的行数保持在最低限度。


编辑²

重新摆弄了你的 SQLfiddle。其中大部分必须以编程方式完成,即。确定哪些类别/多少连接/表别名/列名,但您想从ID列引用的任何表开始,以便为这些连接提供一个可靠的起点,我刚刚创建了该users表以进行说明。

CREATE TABLE users (`ID` varchar(16),`name` varchar(16));
INSERT INTO users (`ID`, `name`)
VALUES ('A', 'andrew'), ('B', 'bob'), ('C', 'charla');

和查询:

SELECT u.*,
  gen.value 'gender',
  pos.value 'position',
  loc.value 'location'
FROM users u
  LEFT JOIN yourtable gen
    ON u.ID = gen.ID
      AND gen.category = 'GENDER'
  LEFT JOIN yourtable pos
    ON u.id = pos.id
      AND pos.category = 'POSITION'
  LEFT JOIN yourtable loc
    ON u.id = loc.id
      AND loc.category = 'LOCATION'

和输出:

ID  NAME    GENDER  POSITION    LOCATION
A   andrew  MALE    (null)      COPENHAGEN
A   andrew  MALE    (null)      MADRID
B   bob     MALE    WEBDESIGN   MADRID
B   bob     MALE    SYSADMIN    MADRID
C   charla  FEMALE  (null)      MADRID
C   charla  FEMALE  (null)      AARHUS

我还要确保,由于有可能进行许多连接,您在表中的 3 列(如果不是全部)category上都有索引。ID

于 2012-11-08T16:37:23.427 回答
1

目前的解决方案是为每个类别创建一个子查询。像这样:

SELECT DISTINCT ID
FROM yourtable
WHERE ID IN 
(SELECT ID from yourtable WHERE (Category = 'POSITION' AND Value = 'SYSADMIN'))
AND ID IN 
(SELECT ID from yourtable WHERE (Category = 'LOCATION' AND Value = 'MADRID') OR (Category = 'LOCATION' AND Value = 'COPENHAGEN'))

可以在SQL Fiddle看到工作示例。

它正在工作,但是当我有很多行或检查许多类别时,我担心性能。

于 2012-11-08T23:15:43.210 回答