Home > Back-end >  Troubles with subqueries using union
Troubles with subqueries using union

Time:09-22

I am using union so I can "merge" the data from 3 separate queries. My table has many columns but I have to use only title and ID.

My data:

ID Title 
1 'trainings'  
2 'trainings'
3 'workshops'
4 'workshops'
5 'workshops'
6 'qwerty'
7 'qwerty2'
8 'qwerty3'

What I want to do is show only the titles of Trainings, workshop and combine these other three's as "Others" and then count each one of them . Example:

Count Title
2     trainings
3     workshops
3     others

What I have tried:

select  Title, count(*) as Count From Events where Title like '%Training%' 
group by Title 
union 
select Title, count(*) as Count From Events where Title like '%Workshop%' 
group by Title
union 
select 'Others' as Title,count(*) as Count from Events e where e.Title not like '%workshop%' and e.Title not like '%training%'
Group by Title

But I don't get the desired result, indeed I take 1 as per "Other's" column:

Count Title
1     Others
2     Trainings
3     Workshops

But if I run only this code:

select 'Others' as Title,count(*) as Count from Events e where e.Title not like '%workshop%' and e.Title not like '%training%'
Group by Title

it will work all fine, the "error" is only when I combine with the two others.

Can you please help me with this?

CodePudding user response:

Why not just use a single query with aggregation?

SELECT COUNT(*) AS [Count],
       CASE WHEN Title LIKE '%Training%' THEN 'Trainings' 
            WHEN Title LIKE '%Workshop%' THEN 'Workshops'
            ELSE 'Other'
       END AS Title
FROM dbo.Events
GROUP BY CASE WHEN Title LIKE '%Training%' THEN 'Trainings' 
              WHEN Title LIKE '%Workshop%' THEN 'Workshops'
              ELSE 'Other'
         END;

If you prefer not to repeat the CASE expression, you can use a CTE:

WITH Titles AS(
    SELECT CASE WHEN Title LIKE '%Training%' THEN 'Trainings' 
                WHEN Title LIKE '%Workshop%' THEN 'Workshops'
                ELSE 'Other'
           END AS Title
    FROM dbo.Events)
SELECT COUNT(*) AS [Count],
       Title
FROM Titles
GROUP BY Title;

CodePudding user response:

You can use a case expression for aggregation:

select (case when title in ('Trainings', 'Workshops') then title
             else 'Others'
        end) as title,
       count(*)
from events e
group by (case when title in ('Trainings', 'Workshops') then title
               else 'Others'
          end);

If you don't want to repeat the case expression you can use a lateral join with apply:

select v.title, count(*)
from events e cross join
     (values (case when title in ('Trainings', 'Workshops')
                   then title else 'Others'
              end)
     ) v(title)
group by v.title;

EDIT:

If you need the LIKE you would just extend this (there are no examples in the question where this is necessary):

select v.title, count(*)
from events e cross join
     (values (case when title like '%trainings%' then 'Training'
                   when title like '%workshops%' then 'Workshop'
                   else 'Others'
              end)
     ) v(title)
group by v.title;

CodePudding user response:

SELECT COUNT(ID) AS Count, Title FROM (SELECT ID, CASE WHEN Title IN ('trainings', 'workshops') THEN Title ELSE 'others' END Title FROM Events) AS T GROUP BY Title

CodePudding user response:

Another Way

select * from (
select  count(case when Title like '%trainings%' then 1 end) as trainings,
  count(case when Title like '%workshops%' then 1 end) as workshops,
  count(case when Title not like '%workshops%' and Title not like '%trainings%' then 1 end) as Other from Events
  )tab
  UNPIVOT 
( 
Counts FOR Title IN (trainings, workshops,Other)
) 
AS UnpivotTable order by Counts
  • Related