2014-10-09 3 views
0

Извините за смутное название!объединение нескольких запросов, имеющих один и тот же основной синтаксис

Я строю веб-фильтр, где пользователи смогут нажать на параметры и отфильтровывать результаты с помощью MS-SQL 2012

У меня есть проблема, я бегу 4 запросов на каждом из выбора, чтобы построить фильтр и 1 для результатов.

Игнорирование, как это лучше всего может быть закодирован таким образом, я не перезагружать фильтр запросов каждый раз, мне нужна помощь в том, как я могу объединить 4 запросов, которые производят параметры фильтра и рассчитывает в 1.

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

 select datePart(yy,p.startDate) year, count(p.personId) itemCount 
     from person p 
     where p.field1 = something 
     and p.field2 = somethingElse... 

Есть ли способ запуска ядра и получения списка фильтров и счетчиков (см ниже) все в одном, а не делать каждый по отдельности?

Ниже приведен пример из 2 фильтров, но есть и другие, которые делают подобные вещи, либо производят список из существующих данных, либо создают список на основе до, между и после определенных дат.

--Filter 1 to get years and counts 
with annualList as 
(
    select a.year 
    from table a 
    where a.year > 2000 
) 
select al.year, isnull(count,0) itemCount 
from annualList al 
left join (
     select datePart(yy,p.startDate) year, count(p.personId) itemCount 
     from person p 
     where p.field1 = something 
     and p.field2 = somethingElse... 
    ) group by datePart(yy,p.startDate) persons 
on al.year = persons.year 
order by al.year desc; 

--filter 2 to get group stats 
select anotherList.groupStatus, groupStatusCounts.itemCount 
from (
    select 'Child' as groupStatus 
    union all 
    select 'Adult' as groupStatus 
    union all 
    select 'Pensioner' as groupStatus 
) anotherList 
left join (
    SELECT personStatus.groupStatus, count(personStatus.personId) itemCount 
    FROM (select p.personId 
      case when (p.age between 1 and 17) then 'Child' 
      case when (p.age between 18 and 67) then 'Adult' 
      case when (p.age > 65) then 'Pensioner' 
      end as groupStatus 
      FROM person p 
      --and some other syntax to calculate the age... 
      where p.field1 = something 
      and p.field2 = somethingElse exactly as above query... 
     ) personStatus 
     GROUP BY personStatus.groupStatus 
    ) groupStatusCounts 
ON anotherList.groupStatus = groupStatusCounts.groupStatus 

В качестве примера, используя приведенную ниже набор данных, из regDate и используя группу, я буду иметь возможность получить список лет от 2010-2014 (код filter1 выше).

Используя данные обруча, мне нужно «вычислить» groupStatus, используя случай. Как вы можете видеть из данных данных о рождении, у меня нет записей, где я могу идентифицировать пенсионера, поэтому, как я написал фильтр 2 (см. Код выше), он даст мне фильтры, которые мне нужны, даже если у меня нет данные для его представления.

Пробовал добавить код на SQL Скрипке, к сожалению, это было вчера вечером

INSERT INTO personTable 
    ([PersonID], [dateOfBirth], [regDate]) 
VALUES 
    (1, '1979-01-01 00:00:00', '2010-01-01 00:00:00'), 
    (2, '1979-01-01 00:00:00', '2010-01-01 00:00:00'), 
    (3, '1979-01-01 00:00:00', '2011-01-01 00:00:00'), 
    (4, '1979-01-01 00:00:00', '2011-01-01 00:00:00'), 
    (5, '1979-01-01 00:00:00', '2012-01-01 00:00:00'), 
    (6, '1979-01-01 00:00:00', '2012-01-01 00:00:00'), 
    (7, '1984-01-01 00:00:00', '2012-01-01 00:00:00'), 
    (8, '1992-01-01 00:00:00', '2012-01-01 00:00:00'), 
    (9, '2000-01-01 00:00:00', '2013-01-01 00:00:00'), 
    (10, '2010-01-01 00:00:00', '2014-01-01 00:00:00') 

my example of SQL Fiddle

Результат хотите, чтобы в итоге мне это нужно, чтобы выглядеть на основании результатов, показанных в Fiddle

filter  | Year | groupStatus 
-----------+-----------+-------- 
2010  | 0  | null 
2011  | 2  | null 
2012  | 3  | null 
2013  | 0  | null 
2014  | 3  | null 
child  | null | 2 
adult  | null | 6 
pensioner | null | 0 

Благодарим вас заранее

ответ

0

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

PersonID | GroupStatus | Year 
---------+-------------+-------- 
    1 | Adult  | 2013 
    2 | Adult  | 2013 
    3 | Adult  | 2014 
    4 | Adult  | 2014 
    5 | Adult  | 2014 
    6 | Child  | 2012 
    7 | Child  | 2014 
    8 | Pensioner | 2012 
    9 | Pensioner | 2013 
    10 | Pensioner | 2013 

Из того, что я понимаю, вы пытаетесь получить 2 различные сводки из этой информации без повторения запроса, например,

GroupStatus | ItemCount 
------------+----------- 
    Adult |  5 
    Child |  2 
    Pensioner |  3 

И

Year | ItemCount 
------------+----------- 
    2012 |  2 
    2013 |  4 
    2014 |  4 

Вы можете получить это в единый набор данных с помощью:

SELECT Year, 
     GroupStatus, 
     ItemCount = COUNT(*) 
FROM T 
GROUP BY GROUPING SETS ((Year), (GroupStatus)); 

Который даст единый набор данных:

YEAR GROUPSTATUS  ITEMCOUNT 
------------------------------------ 
NULL Adult   5 
NULL Child   2 
NULL Pensioner  3 
2012 NULL   2 
2013 NULL   4 
2014 NULL   4 

Если вы хотел также включить полные данные, вы можете просто группировать набор группировок со всеми полями, например. (PersonID, Year, GroupStatus).

Examples on SQL Fiddle

EDIT

Ниже запрос дает выход Запрошенный:

WITH AllValues AS 
( SELECT TOP (DATEPART(YEAR, GETDATE()) - 2009) 
      Filter = CAST(2009 + ROW_NUMBER() OVER(ORDER BY object_id) AS VARCHAR(15)), 
      FilterType = 'Year' 
    FROM sys.all_objects o 
    UNION ALL 
    SELECT Filter, 'GroupStatus' 
    FROM (VALUES ('child'), ('Adult'), ('Pensioner')) T (Filter) 
) 
SELECT v.Filter, 
     [Year] = CASE WHEN v.FilterType = 'Year' THEN ISNULL(data.ItemCount, 0) END, 
     GroupStatus = CASE WHEN v.FilterType = 'GroupStatus' THEN ISNULL(data.ItemCount, 0) END 
FROM AllValues AS v 
     LEFT JOIN 
     ( SELECT [Year] = DATENAME(YEAR, t.RegDate), 
        Age = a.Name, 
        ItemCount = COUNT(*) 
      FROM T 
        LEFT JOIN 
        (VALUES 
         (0, 18, 'Child'), 
         (18, 65, 'adult'), 
         (65, 1000000, 'pensioner') 
        ) a (LowerValue, UpperValue, Name) 
         ON a.LowerValue <= DATEDIFF(HOUR, T.dateofbirth, GETDATE())/8766.0 
         AND a.UpperValue > DATEDIFF(HOUR, T.dateofbirth, GETDATE())/8766.0 
      WHERE T.PersonID > 2 
      GROUP BY GROUPING SETS ((DATENAME(YEAR, t.RegDate)), (a.Name)) 
     ) AS data 
      ON ISNULL(data.[Year], data.Age) = v.Filter; 

Example on SQL Fiddle

+0

Вопрос некоторые из «фильтров '(т.е. groupStatus) должен быть «рассчитан» и не входит в систему, чтобы я мог группироваться в первую очередь. Также в вашем примере возврат 'filters' будет основываться только на том, что находится в таблицах. Однако, если у вас есть данные за 2010-2013 годы, но ничто в 2014 году, фильтр не покажет 2010,2011,2012,2013, оставив 2014 год, и это также нужно будет показать. –

+0

Можете ли вы опубликовать некоторые выборочные данные и ожидаемый результат на ваш вопрос, пожалуйста, так как я думаю, что неправильно понял вашу проблему. – GarethD

+0

обновил мой пост, в вашем примере у вас есть записи для groupStats в db для взрослых, детей и пенсионеров. У меня нет этой информации в моем db, у меня только дата рождения, поэтому из этого я должен рассчитать статус. –

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