2015-01-23 2 views
0

Извините, что задал этот вопрос, так как для этой темы так много, но я много общался с общими вопросами Pivot, не найдя решения из-за добавленного измерения I ' с которыми я общаюсь, и я не могу обойти его. Чтобы определить «опыт» экипажей, когда они участвуют в гонке (это была самая простая иллюстрация того, с чем мне приходится иметь дело), ​​мне нужно выяснить для какой-либо гонки, какие предыдущие гонки участвовали в какой-либо части экипажа удобная для пользователя форма, конечно. Если вы не хотите читать структуру, вот the SQL Fiddle Shortcut У меня есть контакты, автомобили и гонки как простые понятия. Затем есть записи, чтобы привязать автомобили к гонкам. И Экипаж, состоящий из контактов в данной машине гонки.Динамическое преобразование/сворачивание данных SQL

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

Например, для Entry ID 5 (== «Быстрый автомобиль» в гонке «Текущая гонка») Мне нужно перечислить команду и сделать отметки X, если они были также в любых предыдущих гонках (== Race ID < ID для проверки) в том же автомобиле «Fast Car».

Конечный результат, который я искал, - хотя столбец «Текущая раса» был бы сверхъестественным, поскольку это отправная точка для проверки в любом случае.

   Current Race | Old Race | Even Older Race 
Gladys Friday  X    X   X 
Mandy Lifeboats  X    X   X 
Justin Case   X  
Candy Barr   X  
Harvey Theryet  X    X   X 

Было бы здорово, если бы вы могли мне помочь, спасибо!

ответ

1

Вы можете сделать это с помощью динамического запроса, который будет «адаптироваться» к тому, что результат будет иметь. Вот пример которым дает * такой же результат, как ваш пример:

DECLARE @entry INT, @race INT, @car INT, @races VARCHAR(8000), @query NVARCHAR(MAX) 
SET @entry = 5 

--SAVE THE RACE ID AND CAR ID OF THE SPECIFIED ENTRY 
SELECT @race = Races_ID, @car = Cars_ID 
FROM dbo.Entries 
WHERE ID = @entry 

--SELECT THE RACES WITH THE SAME CAR WHERE THE CREW MEMBERS OF THE SPECIFIED ENTRY HAVE PARTICIPATED BEFORE 
SELECT cr.ID, cr.contactname, r.ID raceid, r.racename 
INTO #Exp 
FROM dbo.Contacts cr 
INNER JOIN dbo.Crews cs 
ON cr.ID = cs.Contacts_ID 
INNER JOIN dbo.Entries e 
ON cs.Entries_ID = e.ID AND e.Races_ID <= @race AND e.Cars_ID = @car 
LEFT OUTER JOIN dbo.Races r 
ON e.Races_ID = r.ID 
ORDER BY cr.ID, r.ID DESC 

--CREATE THE DINAMIC LIST OF COLUMNS (RACE NAMES) WE'RE GOING TO USE IN THE PIVOT 
SELECT @races = ISNULL(@races + ',[', '[') + r.racename + ']' 
FROM (SELECT DISTINCT raceid, racename FROM #Exp) r 
ORDER BY r.raceid DESC 

--GENERATE AND EXECUTE THE DYNAMIC QUERY 
SET @query = 
'SELECT contactname,' + @races + 
'FROM (SELECT ID contact_id, ID, contactname, racename FROM #Exp) p 
PIVOT 
(COUNT(ID) FOR p.racename IN (' + @races + ')) as pvt 
ORDER BY contact_id' 
EXEC sys.sp_executesql @query 

DROP TABLE #Exp 

Это создаст таблицу 1 и 0, указывающей на Wich предыдущих гонках члены экипажа указанной записи были. Не имеет значения, сколько и сколько рас существует, так как динамический запрос будет адаптироваться, чтобы показать их все.

* В результате этого запроса учитываются гонки с тем же автомобилем, что и указанная запись; на примере, который вы поставили, есть спасательные шлюпки Mandy на Old Race, которые были с другим автомобилем. Может, я неправильно понял вопрос, или это действительно сбивало с толку?

+0

Привет, Джош, спасибо за ответ. Мне нужно немного разобраться, чтобы понять и адаптировать это. На ваш вопрос: возможно, это немного запутанно; моя попытка создать более понятный пример, возможно, усложнила ситуацию, действительно ... – ExternalUse

+0

Спасибо, Джош, я отмечу это как ответ. По-прежнему кажется, что должен быть немного лучший способ объединить это в запрос или CTE, чтобы сделать его применимым для ряда записей, и он немного медленнее при работе с несколькими тысячами записей. Но просто придумать правильный пример - проблема сама по себе ... Я все-таки понял основные моменты. Благодаря! – ExternalUse

1

Предполагая, что контакт может появляться только один раз за гонку, выполнение COUNT по названию гонки приведет к созданию двоичной таблицы, когда человек появляется в гонке или нет. Если по какой-то причине тот же человек может быть в несколько раз же гонки, то вы просто получите число больше 1.

SELECT * 
FROM (
    SELECT ContactName, RaceName FROM [dbo].[Entries] AS e 
    INNER JOIN [dbo].[Races] AS r ON [e].[Races_ID] = r.[ID] 
    INNER JOIN [dbo].[Cars] AS c ON e.[Cars_ID] = c.[ID] 
    LEFT JOIN Crews ON e.ID = Crews.Entries_ID 
    LEFT JOIN Contacts ON [Contacts].[ID] = Crews.Contacts_ID 
) src 
PIVOT (
    COUNT(RaceName) 
    FOR RaceName IN ([Current Race], [Old Race], [Even Older Race]) 
) pvt 
+0

Спасибо, пожалуйста, не думайте, что отсутствие немедленного принятия означает, что мне это неинтересно, мне просто нужно некоторое время переварить это для реального приложения. Я скоро отправлю отчет – ExternalUse

Смежные вопросы