2013-04-26 3 views
1

Это должно быть очень просто, но я просто не могу определить ответ (я буду обвинять его в том, что я был SQL-кодировкой почти 14 часов).SQL Left Join, Cross Join - найти недостающее значение

У меня есть таблица под названием report с полем «Ярлык» и поле «ReportYear». Я знаю, что у меня есть три возможных значения «Ярлык», но не каждый лейбл будет иметь запись за каждый год.

Я могу выбрать четкий список ярлыков и я получаю:

'Regular' 
'Special' 
'None' 

Выполнение некоторых ручного выбора данных здесь, я знаю, что 2011 и 2010 имеют 0 записей с меткой «Специальный», но мне нужен запрос чтобы получить эту информацию вместе, чтобы она не выходила:

'Regular' - '2012' - '5' 
'Regular' - '2011' - '2' 
'Regular' - '2010' - '1' 
'Special' - '2012' - '3' 
'Special' - '2011' - '0' 
'Special' - '2010' - '0' 
'None' - '2012' - '10' 
'None' - '2011' - '5' 
'None' - '2010' - '2' 

Надеюсь, это имеет смысл.

Я знаю, что могу SELECT Count(*), Label FROM (SELECT DISTINCT Label FROM Report) t1 ... но тогда? LEFT JOIN Report t2 ON t1.Label=t2.Label? CROSS JOIN?

Мой мозг жарится.

Помощь?

ответ

1
SELECT 
    L.Label, 
    Y.ReportYear, 
    ReportCount = Count(R.Label) 
FROM 
    (SELECT DISTINCT Label FROM dbo.Report) L 
    CROSS JOIN (SELECT DISTINCT ReportYear FROM dbo.Report) Y 
    LEFT JOIN dbo.Report R 
     ON L.Label = R.Label 
     AND Y.ReportYear = R.ReportYear 
GROUP BY 
    L.Label, 
    Y.ReportYear 

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

Если меня не недопонимание вещи, мне кажется, что вы должны нормализовать Report таблицы таким образом, он имеет ReportLabelID колонку и затем иметь ReportLabel таблицу с различными этикетками. Затем вы можете поставить таблицу ReportLabel вместо запроса DISTINCT выше.

И вы также можете исключить подзапрос ReportYear, параметризуя весь запрос, чтобы принять BeginYear и EndYear или что-то в этом роде. Или вы можете получить Min(ReportYear), Max(ReportYear) из таблицы, и, предположив, что у вас есть индекс в столбце, он может превратить его в запросы (для его получения могут потребоваться два отдельных запроса), затем используйте таблицу чисел или -fly, чтобы генерировать последовательность лет между ними.

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

+0

ДА! Так оно и было. Спасибо огромное! – JMax2012

+0

Добро пожаловать. – ErikE