PIVOT SQL Server Assistance - PullRequest
       4

PIVOT SQL Server Assistance

2 голосов
/ 25 февраля 2011

Учитывая следующую структуру таблицы:

CrimeID | No_Of_Crimes  |   CrimeDate    | Violence | Robbery | ASB

1            1             22/02/2011         Y          Y      N

2            3             18/02/2011         Y          N      N

3            3             23/02/2011         N          N      Y

4            2             16/02/2011         N          N      Y

5            1             17/02/2011         N          N      Y

Есть ли шанс создать набор результатов, который выглядит так с T-SQL?

Category   |  This Week |  Last Week
Violence          1           3
Robbery           1           0
ASB               3           1

Если на прошлой неделе данные должны быть меньше, чем «20.02.2011», а эта неделя должна быть больше или равна «20.02.2011»

Я не ищу кого-то, кто мог бы для меня это кодировать, хотя фрагмент кода был бы полезен :), просто несколько советов о том, возможно ли это, и как мне это делать с SQL Server.

Для информации, в настоящее время я выполняю всю эту агрегацию, используя LINQ на веб-сервере, но для этого требуется, чтобы по сети каждый раз отправлялся этот запрос по 19 МБ. (Таблица имеет много категорий и> 150 000 строк). Я хочу, чтобы БД выполняла всю работу и отправляла только небольшое количество данных по сети

Большое спасибо

Ответы [ 3 ]

3 голосов
/ 25 февраля 2011

РЕДАКТИРОВАТЬ удален неверный sql для ясности РЕДАКТИРОВАТЬ Забудьте выше, попробуйте ниже

select * 
from (
select wk, crime, SUM(number) number
from (
    select case when datepart(week, crimedate) = datepart(week, GETDATE()) then 'This Week'
            when datepart(week, crimedate) = datepart(week, GETDATE())-1 then 'Last Week'
            else 'OLDER' end as wk, 
            crimedate, 
            case when violence ='Y' then no_of_crimes else 0 end as violence, 
            case when robbery ='Y' then no_of_crimes else 0 end as robbery, 
            case when asb ='Y' then no_of_crimes else 0 end as asb 
    from crimetable) as src
UNPIVOT
    (number for crime in 
    (violence, robbery, asb)) as pivtab
group by wk, crime
) z
PIVOT
( sum(number)
for wk in ([This Week], [Last Week])
) as pivtab
2 голосов
/ 25 февраля 2011

Опоздал на вечеринку, но решение с оптимальным планом запроса:

Пример данных

create table crimes(
    CrimeID int, No_Of_Crimes int, CrimeDate datetime,
    Violence char(1), Robbery char(1), ASB char(1));
insert crimes
select 1,1,'20110221','Y','Y','N' union all
select 2,3,'20110218','Y','N','N' union all
select 3,3,'20110223','N','N','Y' union all
select 4,2,'20110216','N','N','Y' union all
select 5,1,'20110217','N','N','Y';

Создание дополнительных данных - всего около 10240 строк в дополнение к 5 выше,каждые 5 - за 2 недели до предыдущего 5. Также создайте индекс, который поможет на crimedate.

insert crimes
select crimeId+number*5, no_of_Crimes, DATEADD(wk,-number*2,crimedate),
violence, robbery, asb
from crimes, master..spt_values
where type='P'

create index ix_crimedate on crimes(crimedate)

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

Стандартный Unpivot для разрыва категорий.

select CrimeID, No_Of_Crimes, CrimeDate, Category, YesNo
from crimes
unpivot (YesNo for Category in (Violence,Robbery,ASB)) upv
where YesNo='Y'

Примечания:

  1. Фильтр для YesNo фактически применяется ПОСЛЕ отмены вызова.Вы можете закомментировать его, чтобы увидеть.

Снять снова, но на этот раз выберите данные только за последнюю неделю и за эту неделю.

select CrimeID, No_Of_Crimes, Category,
    Week = sign(datediff(d,CrimeDate,w.firstDayThisWeek)+0.1)
from crimes
unpivot (YesNo for Category in (Violence,Robbery,ASB)) upv
cross join (select DATEADD(wk, DateDiff(wk, 0, getdate()), 0)) w(firstDayThisWeek)
where YesNo='Y'
  and CrimeDate >= w.firstDayThisWeek -7
  and CrimeDate <  w.firstDayThisWeek +7

Примечания:

  1. (select DATEADD(wk, DateDiff(wk, 0, getdate()), 0)) w(firstDayThisWeek) создает таблицу из одного столбца, в которой столбец содержит ключевую дату для этого запроса, являющуюся первым днем ​​текущей недели (с использованием параметра DATEFIRST)
  2. Фильтр для CrimeDate фактически применяется кОСНОВНОЙ СТОЛ до разворота.План проверки
  3. Sign() просто разбивает данные на 3 сегмента (-1 / 0 / + 1).Добавление +0.1 гарантирует, что есть только два сегмента -1 и + 1.

Последний запрос, поворот к которому / на прошлой неделе

select Category, isnull([1],0) ThisWeek, isnull([-1],0) LastWeek
from
(
    select Category, No_Of_Crimes,
        Week = sign(datediff(d,w.firstDayThisWeek,CrimeDate)+0.1)
    from crimes
    unpivot (YesNo for Category in (Violence,Robbery,ASB)) upv
    cross join (select DATEADD(wk, DateDiff(wk, 0, getdate()), -1)) w(firstDayThisWeek)
    where YesNo='Y'
      and CrimeDate >= w.firstDayThisWeek -7
      and CrimeDate <  w.firstDayThisWeek +7
) p
pivot (sum(No_Of_Crimes) for Week in ([-1],[1])) pv
order by Category Desc

Вывод

Category  ThisWeek    LastWeek
--------- ----------- -----------
Violence  1           3
Robbery   1           0
ASB       3           3
0 голосов
/ 25 февраля 2011

Я бы попробовал это:

declare @FirstDayOfThisWeek date = '20110220';
select cat.category, 
       ThisWeek = sum(case when cat.CrimeDate >= @FirstDayOfThisWeek
                     then crt.No_of_crimes else 0 end), 
       LastWeek = sum(case when cat.CrimeDate >= @FirstDayOfThisWeek
                     then 0 else crt.No_of_crimes end)
from crimetable crt
cross apply (values 
    ('Violence', crt.Violence),
    ('Robbery', crt.Robbery),
    ('ASB', crt.ASB))
    cat (category, incategory)
where cat.incategory = 'Y'
  and crt.CrimeDate >= @FirstDayOfThisWeek-7
group by cat.category;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...