SQL表连接名称值对

时间:2010-09-22 05:14:30

标签: sql

我有这样的表结构:

表:emp_details

id name value

1电话123-456-8765
1地址多伦多
1岁25岁 1性别男性 1名第一名胜利者

表:emp

ID

1
2
3
4


我希望名称值对以平面方式呈现: 我在这个天真的实现中这样做:
选择emp.id作为id,emp1.value作为电话,emp2.​​value作为地址,emp3.value作为年龄,emp4.value作为性别,emp5.value作为名字
 来自emp,
(选择id,emp_details中的值,其中name ='phone')emp1,其中emp1.id = emp.id,
(选择id,emp_details中的值,其中name ='address')emp2,其中emp2.​​id = emp.id,
(选择id,emp_details中的值,其中name ='age')emp3,其中emp3.id = emp.id,
(选择id,emp_details中的值,其中name ='sex')emp4,其中emp4.id = emp.id,
(选择id,emp_details中的值,其中name ='firstname')emp5,其中emp5.id = emp.id

和emp.id = 1

请你建议一个更好的方法吗?

非常感谢!

3 个答案:

答案 0 :(得分:5)

我相信你正在寻找桌子轮换

    SELECT CASE [d.name]
             WHEN 'phone' THEN [d.value]
             ELSE ''
           END AS phone,
           CASE [d.name]
             WHEN 'address' THEN [d.value]
             ELSE ''
           END AS address,
           CASE [d.name]
             WHEN 'age' THEN [d.value]
             ELSE ''
           END AS age,
           CASE [d.name]
             WHEN 'sex' THEN [d.value]
             ELSE ''
           END AS sex,
           CASE [d.name]
             WHEN 'firstname' THEN [d.value]
             ELSE ''
           END AS firstname
    FROM   emp_details d
           INNER JOIN emp e
             ON d.id = e.id
    WHERE  e.id = 1 

这是另一种方式

SELECT phone = Isnull((SELECT [value]
                       FROM   emp_details
                       WHERE  [name] = 'phone'
                              AND [id] = d.[id]),''),
       address = Isnull((SELECT [value]
                         FROM   emp_details
                         WHERE  [name] = 'address'
                                AND [id] = d.[id]),''),
       age = Isnull((SELECT [value]
                     FROM   emp_details
                     WHERE  [name] = 'age'
                            AND [id] = d.[id]),''),
       sex = Isnull((SELECT [value]
                     FROM   emp_details
                     WHERE  [name] = 'sex'
                            AND [id] = d.[id]),''),
       firstname = Isnull((SELECT [value]
                           FROM   emp_details
                           WHERE  [name] = 'firstname'
                                  AND [id] = d.[id]),'')
FROM   emp_details d
       INNER JOIN emp e
         ON d.id = e.id
WHERE  e.id = 1 

答案 1 :(得分:1)

如果设置不同,第一个表格会更容易使用。

你的emp_details表可以安排如下:

ID   phone         address     age     sex   firstname
1    123-123-1234  1 fake st.  12      M     Bob
2    222-222-2222  2 real st.  33      F     Alice

然后,当您选择一行时,您将获得所需的所有数据:

SELECT * FROM emp_details WHERE ID = 1

这将为您提供ID,电话,地址,年龄,性别和ID为1的员工的名字(本例中为Bob)的记录。

您的桌面目前的设置方式只会给您带来巨大的麻烦。如果你还可以,你现在应该修复它。

了解Google上的数据库规范化。

答案 2 :(得分:0)

我相信这应该适用于您,假设您事先知道您感兴趣的属性的名称。此示例将允许空值并将返回缺少属性的行,这仍然允许您返回其他字段给定的身份。

DECLARE @emp_details TABLE (
    id int,
    name varchar(50),
    value varchar(50),
    PRIMARY KEY (id, name)
)

DECLARE @emp TABLE (
    id int PRIMARY KEY
)

INSERT INTO @emp_details (
    id,
    name,
    value
)
VALUES
    (1, 'phone', '123-456-8765'),
    (1, 'address', 'Toronto'),
    (1, 'age', '25'),
    (1, 'sex', 'male'),
    (1, 'firstname', 'victor')

INSERT INTO @emp (
    id
)
VALUES
    (1),
    (2),
    (3),
    (4)

SELECT
    emp.id AS id,
    empphone.value AS phone,
    empaddress.value AS address,
    empage.value AS age,
    empsex.value AS sex,
    empfirstname.value AS firstname
FROM
    @emp emp
    LEFT JOIN @emp_details empphone
        ON emp.id = empphone.id
            AND empphone.name = 'phone'
    LEFT JOIN @emp_details empaddress
        ON emp.id = empaddress.id
            AND empaddress.name = 'address'
    LEFT JOIN @emp_details empage
        ON emp.id = empage.id
            AND empage.name = 'age'
    LEFT JOIN @emp_details empsex
        ON emp.id = empsex.id
            AND empsex.name = 'sex'
    LEFT JOIN @emp_details empfirstname
        ON emp.id = empfirstname.id
            AND empfirstname.name = 'firstname'
WHERE
    emp.id = 1