Нужна помощь с SQL Query - PullRequest
3 голосов
/ 02 июня 2010

Скажите, у меня есть 2 таблицы:

Person

 - Id
 - Name

PersonAttribute

 - Id
 - PersonId
 - Name
 - Value

Далее, скажем, у каждого человека было 2 атрибута (скажем, пол и возраст). Пример записи будет выглядеть так:

Person->Id = 1
Person->Name = 'John Doe'

PersonAttribute->Id = 1
PersonAttribute->PersonId = 1
PersonAttribute->Name = 'Gender'
PersonAttribute->Value = 'Male'

PersonAttribute->Id = 2
PersonAttribute->PersonId = 1
PersonAttribute->Name = 'Age'
PersonAttribute->Value = '30'

Вопрос: как мне сделать запрос, чтобы получить такой результат:

«Джон Доу», «Мужчина», «30»

Ответы [ 8 ]

4 голосов
/ 02 июня 2010
SELECT p.name, p1.Value, p2.Value 
     FROM Person p, PersonAttribute p1, PersonAttribute p2 
     WHERE p.Id = p1.PersonId AND p.Id = p2.PersonId 
        AND p1.Name = 'Gender' AND p2.Name = 'Age'
3 голосов
/ 02 июня 2010

Я думаю, вам нужно изменить схему. Почему нет?

Person

 - Id
 - Name
 - Gender
 - Birthday
...
2 голосов
/ 02 июня 2010

Хранение пар имя-значение дает гибкость, но очень громоздко для запроса. Взгляните на http://www.simple -talk.com / сообщество / блоги / philfactor / archive / 2008/05/29 / 56525.aspx

2 голосов
/ 02 июня 2010

ВЫБРАТЬ p.Name, g.Value, a.Value
ИЗ ЛИЦА ВНУТРЕННЕГО СОЕДИНЕНИЯ PersonAttribute g ON p.Id = g.Id AND g.Name = "Gender"
INNER JOIN PersonAttribute a ON p.Id = a.Id AND a.Name = "Age"

1 голос
/ 03 июня 2010

Нет простого способа сделать это.

Концепция сводной таблицы (уже упоминавшейся в другом ответе) - это в основном то, что вы ищете, за исключением того, что сводные таблицы требуют, чтобы вы знали имена столбцов, которые вы хотите использовать. Очевидно, это проблема, когда вы хотите использовать всю мощь такой конструкции стола!

В моей предыдущей жизни я просто остановился на количестве столбцов X, например, 20-30, и если их не было, то в набор строк было включено несколько нулевых значений. Ничего страшного.

select piv.name, 
    max(case piv.a_name when 'Gender' then piv.a_value else null end) as Gender,
    max(case piv.a_name when 'Age' then piv.a_value else null end) as Age,
    max(case piv.a_name when 'Hobby' then piv.a_value else null end) as Hobby
from 
(select p.name as name, pa.name as a_name, pa.value as a_value 
from person p, personattribute pa
where p.id = pa.personid) piv
group by piv.name

Это сгенерирует вывод примерно так:

   name    | gender | age |  hobby  
-----------+--------+-----+---------
 Bob Swift | Male   |     | Reading
 John Doe  | Male   | 30  | 
(2 rows)

Что чертовски близко к тому, что вы ищете. Я бы оставил все это на уровне приложений.

Я также настоятельно рекомендую включить атрибут NAME как часть возвращаемого значения, чтобы обеспечить контекст для VALUE.

Эти типы так называемых конструкций Entity-Attribute часто заканчиваются тем, что им приходится полагаться на комбинацию серверных функций, хранимых процедур и жестко закодированных запросов.

1 голос
/ 02 июня 2010

Оставляя дизайн в стороне, вы всегда можете PIVOT результат, но вам нужно знать, сколько атрибутов вы выбираете заранее.

0 голосов
/ 02 июня 2010
SELECT Name, g.Value, a.Value
FROM Person, 
PersonAttribute g INNER JOIN ON g.Name = "Gender", 
PersonAttribute a INNER JOIN ON a.Name = "Age"
0 голосов
/ 02 июня 2010

Вам нужно ПРИСОЕДИНИТЬСЯ к двум таблицам.Википедия дает довольно хорошее объяснение JOIN: http://en.wikipedia.org/wiki/Join_%28SQL%29

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...