Самый эффективный способ объединения полей в динамическую структуру таблицы - PullRequest
2 голосов
/ 28 марта 2012

У нас есть три таблицы, в которых хранится информация о документе, которую я назову таблицей A, B и C. В таблице A хранятся основные поля для указанных документов (например, имя и размер файла и другая общая информация).Чтобы динамически добавлять новые поля, мы используем Таблицу B для хранения списка новых полей и их типов данных (определяемых перечислением), а Таблицу C - для хранения значений для этих полей.

Table A
ID   - PK int
FieldX...
FieldY...
FieldZ...

Table B
Id   - PK int
Name - nvarchar(max)
Type - int

Table C
Id    - PK int
AId   - FK to table A int
BId   - FK to table B int
Value - nvarchar(max)

То, что мы хотим сделать максимально эффективно, - это извлечь значения из таблицы C в качестве дополнительного столбца в запросе из таблицы A. Прямо сейчас вот как я делаю это для каждого дополнительногополе в таблице B.

select (select c.value 
        from B b, C c
        where c.AId = a.Id 
        and c.Bid = b.Id
        and b.Name = 'Dynamic Field Name') As 'Dynamic Field Name'
From A a

У нас есть база данных с таблицей A, заполненной 36000 строк.Для каждого дополнительного динамического поля, добавляемого в запрос, его добавление составляет около 4 секунд к общему времени завершения запроса, в результате чего запрос, содержащий 10 динамических полей, занимает не менее 40 секунд.Реально, мы хотим, чтобы любой запрос заканчивался до 10. Есть ли способ написать это более эффективно?

Ответы [ 2 ]

0 голосов
/ 28 марта 2012

Возможно, такой запрос тоже подойдет:

select a.id
      ,MAX(CASE WHEN b.Name = 'Dynamic Field Name' THEN c.value END) As Dynamic_Field_Name
      ,MAX(CASE WHEN b.Name = 'Dynamic Field Name 2' THEN c.value END) As Dynamic_Field_Name2
  from A a,  B b, C c
  where c.AId = a.Id 
    and c.Bid = b.Id
    and b.Name IN ('Dynamic Field Name', 'Dynamic Field Name 2')
  group by a.id

Та же идея, вы хотите сделать только один проход по таблице, а не поиск по каждой строке. Совокупность состоит в том, чтобы сжать разреженную матрицу в одну строку (т. Е. В строке будет только одно значение динамического поля, каждая строка имеет отдельный столбец со значением). Не знаю, как это будет работать.

0 голосов
/ 28 марта 2012

Прежде всего, ваш запрос может дать вам ошибки, потому что вы не определили C. (A + B) как уникальный.Если в комбинации C A+B имеется несколько значений, это приводит к сбою подзапроса с

Msg 512, Level 16, State 1, Line 1
Subquery returned more than 1 value.

Предполагая, что он уникален, тогда вы должны быть в безопасности, просто оставив их вместе, чтобы использовать SETоперации на основе.

select a.*,
       c1.value [Dynamic Field Name 1],
       c2.value [Dynamic Field Name 2]
From A a
JOIN B b1 on b1.Name = 'Dynamic Field Name1'
LEFT JOIN C c1 on c1.AId = a.Id and c.Bid = b1.Id
JOIN B b2 on b2.Name = 'Dynamic Field Name2'
LEFT JOIN C c2 on c2.AId = a.Id and c2.Bid = b2.Id

Использование подзапроса на уровне SELECT заставляет каждую запись и каждое динамическое поле выполняться как мини-выбор = очень медленно.

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