Home > OS >  T-SQL Query - how to create a new temporary "location" in a table under a location column
T-SQL Query - how to create a new temporary "location" in a table under a location column

Time:11-12

While running a query that selects a Location, date, and visitIDs, I need to be able to select a new combined location name (eg. "LOC3 4") which includes all the rows from locations "LOC3" and "LOC4". This new dataset need to have its own location name so that I can group the data by Location in an SSRS report.

Below is a very simplified version of my existing query plus what I want to query -- the combined location that doesn't exist yet.

SELECT Date, Location, Count(VisitID)
FROM database
WHERE Location = LOC1
UNION ALL
-- repeat for LOC2-5 
UNION ALL
SELECT Date, Location, VisitID
FROM database
WHERE Location = LOC3 4

Expected Results (includes combined location with expected result)

expected data

CodePudding user response:

You can use a conditional expression to assign the new location. In SQL Server, it is handy to do this in cross apply :

select t.date, x.new_location, count(*) cnt
from mytable t
cross apply ( values 
    (case when location in ('LOC3', 'LOC4') then 'LOC3-4' else location end)
) x(new_location)
group by t.date, x.new_location

CodePudding user response:

To Expand on GMB's answer, I think you need one or more UNIONS in the cross apply to include both the original and the mapped locations.

select t.date, x.location, count(*) cnt
from mytable t
cross apply (
    select location
    union all
    select 'LOC3-4' AS location where t.location in ('LOC3', 'LOC4')
    union all
    select 'LOC2-5' AS location where t.location in ('LOC2', 'LOC3', 'LOC4', 'LOC5')
) x
group by t.date, x.location

A better solution may be to use a table driven mapping that associates original locations with mapped/combined locations.

declare @mapping table (location varchar(10), mapped_location varchar(10))
insert @mapping
values
    ('LOC3', 'LOC3-4'),('LOC4', 'LOC3-4'),
    ('LOC2', 'LOC2-5'),('LOC3', 'LOC2-5'),('LOC4', 'LOC2-5'),('LOC5', 'LOC2-5')

select t.date, x.location, count(*) cnt
from mytable t
cross apply (
    select location
    union all
    select m.mapped_location as location
    from @mapping m
    where m.location = t.location
) x
group by t.date, x.location

If there are no matching entries, you only count the original location. The mapping can also define multiple mapped locations for a single source location.

Both of the above generate results like:

date location cnt
2022-10-31 LOC1 1
2022-10-31 LOC2 2
2022-10-31 LOC2-5 14
2022-10-31 LOC3 3
2022-10-31 LOC3-4 7
2022-10-31 LOC4 4
2022-10-31 LOC5 5

(using abbreviated test data)

See this db<>fiddle for a demo.

  • Related