简体   繁体   中英

MS Access Transform / Pivot to SQL Server with grouping

I know similar questions have been asked before, however the grouping is throwing me off and hopefully I can get some help. I currently have a working MS Access model that does custom calculations to an Oracle connection, however my data is now pushing the 2GB mark with the custom calculations and trying SQL Server Express as an alternative and need a bit of help.

The database structure is from a 3rd party application so have to live with what I have - its UGLY.

ID | ATRSTUDY |  ENDTIME           | NAME        | COUNT
---+----------+--------------------+-------------+-------
1  | A        | Jan 1, 18 00:15    | NorthBound  | 10
2  | A        | Jan 1, 18 00:15    | SouthBound  | 20
3  | A        | Jan 1, 18 00:15    | Both Dir    | 30
4  | B        | Jan 1, 18 00:15    | EastBound   | 30
5  | B        | Jan 1, 18 00:15    | WestBound   | 40
5  | B        | Jan 1, 18 00:15    | Both Dir    | 70

My existing MS-Access SQL is:

TRANSFORM Sum(CountData_Local.Count) AS SumOfCount
SELECT CountData_Local.ATRSTUDY, DateValue([CountData_Local]![ENDTIME]) AS CNTDATE, CountData_Local.ENDTIME
FROM DataVariables, CountData_Local
GROUP BY CountData_Local.ATRSTUDY, DateValue([CountData_Local]![ENDTIME]), CountData_Local.ENDTIME
PIVOT IIf([NAME]="EastBound" Or [NAME]="NorthBound" Or [NAME]="First Direction","C1",IIf([NAME]="WestBound" Or [NAME]="SouthBound" Or [NAME]="Second Direction","C2",IIf([NAME]="Both Dir","TC")));

The end result I am try to achieve is a pivot table that combines the 3 rows into one row as follows:

ATRSTUDY |  CNDDATE  | ENDTIME | C1 | C2 | TC
---------+-----------+---------+----+----+---
   A     | Jan 1, 18 | 00:15   |10  | 20 | 30
   B     | Jan 1, 18 | 00:15   |30  | 40 | 70

Thanks in advance!

MS SQL Server has PIVOT to do such things.
And CASE can be used to group those names as codes.

Example snippet:

--
-- Using a table variable for easy testing in the example
--
declare @Count_data table (id int identity(1,1) primary key, ATRSTUDY varchar(1), ENDTIME datetime, NAME varchar(30), [COUNT] int);
insert into @Count_data (ATRSTUDY, ENDTIME, NAME, [COUNT]) values
('A','2018-01-01T18:00:15','NorthBound',10),
('A','2018-01-01T18:00:15','SouthBound',20),
('A','2018-01-01T18:00:15','Both Directions',30),
('B','2018-01-01T18:00:15','EastBound',30),
('B','2018-01-01T18:00:15','WestBound',40),
('B','2018-01-01T18:00:15','Both Directions',70);

select ATRSTUDY, ENDDATE, ENDTIME, [C1], [C2], [TC]
from (
   select
    d.ATRSTUDY,
    cast(d.ENDTIME as date) as ENDDATE,
    left(cast(d.ENDTIME as time),5) as ENDTIME,
    (case -- if the Name column has a Case-Insensitive collation then lower or upper case won't matter.
     when d.Name in ('eastbound', 'northbound', 'first direction') then 'C1'
     when d.Name in ('westbound', 'southbound', 'second direction') then 'C2'
     when d.Name like 'both dir%' then 'TC'
     else d.Name
     end) as ColName,
     d.[count]
   From @Count_data d
) as q
pivot (
    sum([count]) 
    for ColName in ([C1], [C2], [TC])
) as pvt
order by ATRSTUDY, ENDDATE, ENDTIME;

Output:

ATRSTUDY ENDDATE    ENDTIME C1 C2 TC
-------- ---------- ------- -- -- --
A        2018-01-01 18:00   10 20 30
B        2018-01-01 18:00   30 40 70

Here is my SQL to date. Still having a bit of trouble with showing date and time and adding a filter for a date range which I currently have filtered out.

Perfect situation, date would be a between A and B.

Select atrstudy, endtime, sum(c1), sum(c2), sum(tc) from
   (
   with t as
   (
select
   sdata.oid,
   sdata.atrstudy,
   case upper(datatyp.name)
   when 'EASTBOUND' then 'C1'
   when 'NORTHBOUND' then 'C1'
   when 'FIRST DIRECTION' then 'C1'
   when 'WESTBOUND' then 'C2'
   when 'SOUTHBOUND' then 'C2'
   when 'SECOND DIRECTION' then 'C2'
   when 'BOTH DIRECTIONS' then 'TC'
else datatyp.name
end as namedir,
/* trunc(datadtlbs.starttime) as starttime, */
endtime as endtime,
datadtlbs.count as counttot,
sdata.gcrecord
from roy.atrstudydata sdata
left outer join roy.atrstudydatadtl datadtl
on sdata.oid = datadtl.parent
join roy.atrstudydattyp datatyp
on sdata.direction = datatyp.oid
left outer join roy.atrstudydatadtlbs datadtlbs
on datadtl.oid = datadtlbs.oid
/* where trunc(datadtlbs.endtime) > '31-DEC-15'  can remove this where clause*/)
select atrstudy, endtime, C1, C2, TC from t
pivot
(sum(COUNTtot) for NAMEdir in ('C1' as C1, 'C2' as C2, 'TC' as TC)))
group by atrstudy, endtime
order by atrstudy, endtime

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM