选择与任意标准匹配的行

时间:2012-11-08 16:31:37

标签: mysql select

我有一个像这样的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

的ID
  

((LOCATION = COPENHAGEN或LOCATION = MADRID)和(GENDER = MALE))

应该返回A,B

另一个例子:

给我所有IDS

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

应该返回C

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

更新

我已经使用示例数据创建了此sql fiddle,并提出了一个无效的解决方案。

2 个答案:

答案 0 :(得分: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' )

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


Edit²

re-fiddled your 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

我还要确保,在多个加入的可能性下,您有category以及ID的索引,如果不是表格中的所有3列

答案 1 :(得分: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看到工作示例。

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