Проблема создания представления, содержащего таблицы поиска - PullRequest
0 голосов
/ 23 февраля 2009

должно быть достаточно простым, но это вызывает у меня пару проблем.

У меня есть набор данных, подобный следующему:

User
  UserID
  Name
  Age

UserPropertyValues
  UserID
  PropertyCodeValueID

PropertyCodes
  PropertyCodeID
  PropertyCodeName

PropertyCodeValues
  PropertyCodeValueID
  PropertyCodeID
  PropertValue

Теперь давайте предположим, что таблицы содержат следующие данные:

1  John  25
2  Sarah  34

1  2
1  3
2  1
2  3

1  FavColour
2  CarMake
3  PhoneType

1  1  Blue
2  1  Yellow
3  2  Ford
4  3  Mobile
5  3  Landline

Теперь из этого я хочу создать представление для возврата сведений о пользователе, а также значений свойств для кодов свойств 1 и 2 следующим образом:

John 25 Yellow Ford
Sarah 34 Blue Ford

Запросы, которые я пробовал до сих пор, имеют тенденцию возвращать повторяющиеся строки данных:

John 25 Yellow
John 25 Ford
Sarah 34 Blue
Sarah 34 Ford

Любая помощь приветствуется, спасибо всем заранее.

Ответы [ 3 ]

2 голосов
/ 23 февраля 2009

Входные данные:

DECLARE @User TABLE (UserID INT, Name VARCHAR(10), Age INT)
INSERT INTO @User
SELECT 1,  'John',  25 UNION
SELECT 2,  'Sarah',  34
DECLARE @UserPropertyValues TABLE(UserID INT, PropertyCodeValueID INT)
INSERT INTO @UserPropertyValues
SELECT 1, 2 UNION
SELECT 1, 3 UNION
SELECT 2, 1 UNION
SELECT 2,  3
DECLARE @PropertyCodes 
  TABLE (PropertyCodeID INT, PropertyCodeName VARCHAR(10))
INSERT INTO @PropertyCodes
SELECT 1,  'FavColour' UNION
SELECT 2,  'CarMake' UNION
SELECT 3,  'PhoneType'
DECLARE @PropertyCodeValues TABLE (PropertyCodeValueID INT, 
  PropertyCodeID INT, PropertValue VARCHAR(10))
INSERT INTO @PropertyCodeValues
SELECT 1,  1,  'Blue' UNION
SELECT 2,  1,  'Yellow' UNION
SELECT 3,  2,  'Ford' UNION
SELECT 4,  3,  'Mobile' UNION
SELECT 5,  3,  'Landline'

Если два результата - это все, что вам нужно в результате, и у каждого пользователя есть эти свойства, попробуйте следующее:

SELECT U.Name, U.Age, PCVFC.PropertValue, PCVCM.PropertValue 
FROM @User U
INNER JOIN @UserPropertyValues UPVFC ON U.UserID = UPVFC.UserID 
INNER JOIN @PropertyCodeValues PCVFC 
  ON UPVFC.PropertyCodeValueID = PCVFC.PropertyCodeValueID 
    AND PCVFC.PropertyCodeID = 1
INNER JOIN @UserPropertyValues UPVCM ON U.UserID = UPVCM.UserID 
INNER JOIN @PropertyCodeValues PCVCM 
  ON UPVCM.PropertyCodeValueID = PCVCM.PropertyCodeValueID 
    AND PCVCM.PropertyCodeID = 2

[править] Но для обработки возможных значений NULL лучше использовать это:

SELECT U.Name, U.Age, FC.PropertValue, CM.PropertValue 
FROM @User U
LEFT JOIN (
  SELECT UserID, PropertValue FROM @UserPropertyValues  UPV
    INNER JOIN @PropertyCodeValues PCV 
      ON UPV.PropertyCodeValueID = PCV.PropertyCodeValueID 
        AND PCV.PropertyCodeID = 1
) FC ON U.UserID = FC.UserID
LEFT JOIN (
  SELECT UserID, PropertValue FROM @UserPropertyValues  UPV
    INNER JOIN @PropertyCodeValues PCV 
      ON UPV.PropertyCodeValueID = PCV.PropertyCodeValueID 
        AND PCV.PropertyCodeID = 2
) CM ON U.UserID = CM.UserID
1 голос
/ 23 февраля 2009

Что вам действительно нужно, так это отказаться от этого типа дизайна базы данных как можно скорее. Это никогда не будет эффективным или эффективным. Чтобы получить три типа значений, вы должны присоединиться к таблице три раза. Как только у вас будет 30 или сорок различных типов информации, вам нужно будет присоединиться к таблице много раз (и при этом осталось только несколько). Далее, каждый раз, когда вам нужна любая информация, вам нужно присоединиться к этой таблице. Я вижу, что это создает серьезную проблему блокировки в вашей базе данных. Люди, которые изначально проектировали одну из баз данных, с которыми я работаю, сделали это и вызвали огромную проблему с производительностью, когда компания превратилась из одного или двух клиентов в крупнейшего в нашей отрасли.

Если в свойствах, вероятно, будет только одна записанная запись на человека, поместите их в таблицу пользователей. Если они будут иметь несколько записей, то создайте отдельную таблицу для каждого типа информации (одну для хонов, одну для электронной почты, одну для cartype и т. Д.), Поскольку информация, которую вы в конечном итоге захотите собрать, обычно будет больше, чем простое значение различаются для каждого типа информации они должны быть в отдельных таблицах. Затем, когда вам нужно увидеть только одно значение (например, номер телефона, но не адрес электронной почты), вы присоединяетесь только к этой таблице и не мешаете людям, пытающимся получить доступ к электронной почте, но не к номеру телефона. И если у вас есть желтый Ford или белый Honda, он будет храниться только в одной записи в таблице auto, а не в двух записях свойств в вашем дизайне.

0 голосов
/ 23 февраля 2009
SELECT 
  u.[Name],
  u.Age,
  pcv1.PropertValue,
  pcv2.PropertValue
FROM 
  Users  u
  LEFT JOIN 
  ( UserPropertyValues upv1 
    JOIN PropertyCodeValues pcv1 ON 
    upv1.PropertyCodeValueID = pcv1.PropertyCodeValueID 
    AND pcv1.PropertyCodeID = 1
  )
  ON upv1.UserID = u.UserID
  LEFT JOIN (
    UserPropertyValues upv2 
    JOIN PropertyCodeValues pcv2 ON 
    upv2.PropertyCodeValueID = pcv2.PropertyCodeValueID 
    AND pcv2.PropertyCodeID = 2
  )
  ON upv2.UserID = u.UserID

Редактировать: я переименовал пользователя в пользователей

Edit2: разрешено для нуля (не введенные значения)

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