(store procedure) combine result 2 rows into 1 row result - sql

can i combine result row 3 and row 4 into 1 row record?
select #fYear as [Year],
(case when main.Description in ('Kecil', 'Tanah') then 'JK'
else main.Description
end) as description,
--CardType,
sum(case when MONTH(blue.AppliedDate) = 1 then 1 else 0 end) as Jan_Collection,
sum(case when MONTH(blue.AppliedDate) = 2 then 1 else 0 end) as Feb_Collection,
...
from tblR as main
left join tblP as b on main.requestorid = b.requestorid
left join tblB as blue on b.partyid = blue.partyid and YEAR(blue.AppliedDate) = #fYear
group by (case when main.Description in ('Kecil', 'Tanah') then 'JK'
else main.Description
end)
this output like:
https://gyazo.com/d930cb2aee92f90ba31dd543d6ca64f3
but can i display combine record row 3 and 4 into 1 record like JK like this picture: https://gyazo.com/a89ed2fa04b51135bf8601d59d4af0b2
Thanks.

If you want to combine those specific descriptions, you can use a case, both in the select and the group by:
select #fYear as [Year],
(case when description in ('kecil', 'Tanah') then 'JK'
else main.Description
end) as Description,
sum(case when MONTH(blue.AppliedDate) = 1 then 1 else 0 end) as Jan_Collection,
sum(case when MONTH(blue.AppliedDate) = 2 then 1 else 0 end) as Feb_Collection,
...
from tblR main left join
tblP b
on main.requestorid = b.requestorid left join
tblB
blue
on b.partyid = blue.partyid and YEAR(blue.AppliedDate) = #fYear
group by (case when description in ('kecil', 'Tanah') then 'JK'
else main.Description
end)

Related

SQL ANY as a function instead of an operator

I need to count users that match certain conditions. To do that I need to join some tables and check if any of the grouping combination match the condition.
The way I implemented that now is by having a nested select that counts original matches and then counting the rows that have at least one result.
SELECT
COUNT(case when NestedCount1 > 0 then 1 else null end) as Count1,
COUNT(case when NestedCount2 > 0 then 1 else null end) as Count2,
COUNT(case when NestedCount3 > 0 then 1 else null end) as Count3
FROM
(SELECT
COUNT(case when Type = 1 then 1 else null end) as NestedCount1,
COUNT(case when Type = 2 then 1 else null end) as NestedCount2,
COUNT(case when Type = 2 AND Condition = 1 then 1 else null end) as NestedCount3
FROM [User]
LEFT JOIN [UserGroup] ON [User].Id = [UserGroup].UserId
LEFT JOIN [Group] ON [UserGroup].GroupId = [Group].Id
GROUP BY [User].Id) nested
What irks me is that the counts from the nested select are only used to check existence. However since ANY in SQL is only an operator I cannot think of a cleaner way on how to rewrite this.
The query returns correct results as is.
I'm wondering if there is any way to rewrite this that would avoid having intermediate results that are only used to check existence condition?
Sample imput User.csv Group.csv UserGroup.csv
Expected results: 483, 272, 121
It might be possible to simplify that query.
I think that the group on the UserId can be avoided.
By using distinct conditional counts on the user id.
Then there's no need for a sub-query.
SELECT
COUNT(DISTINCT case when [User].[Type] = 1 then [User].Id end) as Count1,
COUNT(DISTINCT case when [User].[Type] = 2 then [User].Id end) as Count2,
COUNT(DISTINCT case when [User].[Type] = 2 AND Condition = 1 then [User].Id end) as Count3
FROM [User]
LEFT JOIN [UserGroup] ON [UserGroup].UserId = [User].Id
LEFT JOIN [Group] ON [Group].Id = [UserGroup].GroupId;
SELECT
SUM(case when NestedCount1 > 0 then 1 else 0 end) as Count1,
SUM(case when NestedCount2 > 0 then 1 else 0 end) as Count2,
SUM(case when NestedCount3 > 0 then 1 else 0 end) as Count3
FROM
(
SELECT
[User].Id,
COUNT(case when Type = 1 then 1 else 0 end) as NestedCount1,
COUNT(case when Type = 2 then 1 else 0 end) as NestedCount2,
COUNT(case when Type = 2 AND Condition = 1 then 1 else 0 end) as NestedCount3
FROM [User]
LEFT JOIN [UserGroup] ON [UserGroup].UserId = [User].Id
LEFT JOIN [Group] ON [Group].Id = [UserGroup].GroupId
GROUP BY [User].Id
) nested

Trying to introduce a simple new condition to a JOIN query

I am using SQLite and I had someone help me construct this JOIN query which works quite well, but now I need to add another condition but I am having trouble introducing it to the query without it breaking.
In both tables used in the JOIN there is a column called EventId and I want to introduce the simple condition...
WHERE EventId = 123456
Below you can see a working example of the query itself along with two comments where I have tried to introduce the new condition and failed (because I'm bad at SQL).
SELECT t.MicrosoftId,
SUM(CASE WHEN name = 'necktie' THEN 1 ELSE 0 END) as 'necktie',
SUM(CASE WHEN name = 'shirt' THEN 1 ELSE 0 END) as 'shirt',
SUM(CASE WHEN name = 'suit' THEN 1 ELSE 0 END) as 'suit',
SUM(CASE WHEN name = 'man' THEN 1 ELSE 0 END) as 'man',
SUM(CASE WHEN name = 'male' THEN 1 ELSE 0 END) as 'male'
FROM TagsMSCV t
/* <---- WHERE t.EventId = 123456 (fails here...) */
LEFT JOIN
(SELECT i.MicrosoftId
FROM Images i
GROUP BY i.MicrosoftId) i
ON i.MicrosoftId = t.MicrosoftId
WHERE t.name IN ('necktie','shirt','suit','man','male')
/* <---- AND WHERE t.EventId = 123456 (fails here too...) */
GROUP BY t.MicrosoftId
try like below
select t1.* from ( SELECT t.MicrosoftId,
SUM(CASE WHEN name = 'necktie' THEN 1 ELSE 0 END) as 'necktie',
SUM(CASE WHEN name = 'shirt' THEN 1 ELSE 0 END) as 'shirt',
SUM(CASE WHEN name = 'suit' THEN 1 ELSE 0 END) as 'suit',
SUM(CASE WHEN name = 'man' THEN 1 ELSE 0 END) as 'man',
SUM(CASE WHEN name = 'male' THEN 1 ELSE 0 END) as 'male'
FROM TagsMSCV t WHERE t.EventId = 123456
and name IN ('necktie','shirt','suit','man','male') group by t.MicrosoftId
) t1
You did mistake to create subquery and as 2nd subquery no need group by as there no aggregate function used
It should be in WHERE section, but without second WHERE keyword:
SELECT t.MicrosoftId,
SUM(CASE WHEN name = 'necktie' THEN 1 ELSE 0 END) as 'necktie',
SUM(CASE WHEN name = 'shirt' THEN 1 ELSE 0 END) as 'shirt',
SUM(CASE WHEN name = 'suit' THEN 1 ELSE 0 END) as 'suit',
SUM(CASE WHEN name = 'man' THEN 1 ELSE 0 END) as 'man',
SUM(CASE WHEN name = 'male' THEN 1 ELSE 0 END) as 'male'
FROM TagsMSCV t
LEFT JOIN
(SELECT i.MicrosoftId
FROM Images i
GROUP BY i.MicrosoftId) i
ON i.MicrosoftId = t.MicrosoftId
WHERE t.name IN ('necktie','shirt','suit','man','male')
AND t.EventId = 123456
GROUP BY t.MicrosoftId

Combining two aggregate queries into one

For some context, I am making an image browser which is connected to an SQLite database. Within the browser, similar images are grouped into an event (EventId) and each image (MicrosoftId) is labelled with a few tags (name).
I have these two queries on the same table (TagsMSCV) but pulling out different information. Ultimately I need to combine the information in my browser so if it was possible to combine these two queries (maybe with a JOIN?) it would be a lot faster and convenient for me. Both results of these queries share the EventId column.
1st Query ():
SELECT EventId as 'event', count(*) as 'size',
SUM(case when tag_count = 1 then 1 else 0 end) as '1',
SUM(case when tag_count = 2 then 1 else 0 end) as '2',
SUM(case when tag_count = 3 then 1 else 0 end) as '3'
FROM (SELECT EventId, MicrosoftId,
SUM(case when name in ('indoor', 'cluttered', 'screen') then 1 else 0 end) as tag_count
FROM TagsMSCV GROUP BY EventId, MicrosoftId) TagsMSCV
GROUP BY EventId ORDER BY 3 DESC, 2 DESC, 1 DESC
2nd Query
SELECT EventId,
SUM(CASE WHEN name = 'indoor' THEN 1 ELSE 0 END) as indoor,
SUM(CASE WHEN name = 'cluttered' THEN 1 ELSE 0 END) as cluttered,
SUM(CASE WHEN name = 'screen' THEN 1 ELSE 0 END) as screen
FROM TagsMSCV WHERE name IN ('indoor', 'cluttered', 'screen')
GROUP BY EventId
As you can see in both queries I am feeding in the tags 'necktie' 'man', 'male' and getting different information back.
SQL Fiddle Here: https://www.db-fiddle.com/f/f8WNimjmZAj1XXeCj4PHB8/3
You should do this all in one query:
SELECT EventId as event, count(*) as size,
SUM(case when (indoor + cluttered + screen) = 1 then 1 else 0 end) as tc_1,
SUM(case when (indoor + cluttered + screen) = 2 then 1 else 0 end) as tc_2,
SUM(case when (indoor + cluttered + screen) = 3 then 1 else 0 end) as tc_3,
SUM(indoor) as indoor,
SUM(cluttered) as cluttered,
SUM(screen) as screen
FROM (SELECT EventId, MicrosoftId,
SUM(CASE WHEN name = 'indoor' THEN 1 ELSE 0 END) as indoor,
SUM(CASE WHEN name = 'cluttered' THEN 1 ELSE 0 END) as cluttered,
SUM(CASE WHEN name = 'screen' THEN 1 ELSE 0 END) as screen
FROM TagsMSCV
GROUP BY EventId, MicrosoftId
) TagsMSCV
GROUP BY EventId
ORDER BY 3 DESC, 2 DESC, 1 DESC;
You need two aggregations to get the information about the tag counts. There is no need to add more aggregations and joins to the query.
You could use an Inner join subquery
SELECT TagsMSCV.EventId as 'event', count(*) as 'size',
SUM(case when tag_count = 1 then 1 else 0 end) as '1',
SUM(case when tag_count = 2 then 1 else 0 end) as '2',
SUM(case when tag_count = 3 then 1 else 0 end) as '3',
t.necktie,
t.man,
t.male
FROM (
SELECT EventId, MicrosoftId,
SUM(case when name in ('necktie' 'man', 'male') then 1 else 0 end) as tag_count
FROM TagsMSCV GROUP BY EventId, MicrosoftId
) TagsMSCV
INNER JOIN (
SELECT EventId,
SUM(CASE WHEN name = 'necktie' THEN 1 ELSE 0 END) as necktie,
SUM(CASE WHEN name = 'man' THEN 1 ELSE 0 END) as man,
SUM(CASE WHEN name = 'male' THEN 1 ELSE 0 END) as male
FROM TagsMSCV WHERE name IN ('necktie' 'man', 'male')
GROUP BY EventId
) t on t.EventId = TagsMSCV.EventId
GROUP BY TagsMSCV.EventId
ORDER BY 3 DESC, 2 DESC, 1 DESC

how to Sum "case when" clause after inner join without duplication

I am a new member of Stackoverflow (and also I'm a new of coding sql) if i do any mistakes about my question please advise me :)
I'm trying to get SUM of Amount in CASE WHEN Clause.
Here is my table
tableA
UserID transid Brand Amount
UserA 109974 MIX 960.00 --BrandMIX=A & B
UserB 109975 B 894.00
UserC 109976 C 350.00
UserC 109977 MIX 300.00 --BrandMIX=C & D
tableB
Row transid Brand
1 109974 A
2 109974 B
3 109975 B
4 109976 C
5 109977 C
6 109977 D
I tried inner join table a and table b on a.soid = b.soid
and when i SUM it, result was wrong due to duplication of transid in table b.
here is my coding.
SELECT UserID
,CASE WHEN COUNT(DISTINCT(b.transid )) <> 0 THEN COUNT(DISTINCT(b.transid ))
ELSE NULL END) AS 'Frequency'
,SUM(Amount) as 'TotalAmount'
,YEAR(transdatetime) AS 'Year'
,SUM (CASE [Brand] WHEN 'AA' THEN 1 ELSE 0 END) AS [BrandA]
,SUM (CASE [Brand] WHEN 'BB' THEN 1 ELSE 0 END) AS [BrandB]
,SUM (CASE [Brand] WHEN 'CC' THEN 1 ELSE 0 END) AS [BrandC]
,SUM (CASE [Brand] WHEN 'DD' THEN 1 ELSE 0 END) AS [BrandD]
,SUM (CASE [Brand] WHEN 'ZZ' THEN 1 ELSE 0 END) AS [BrandZ]
FROM tableA a
INNER tableB b ON a.transid = b.transid
WHERE is_paid = 'N'
GROUP BY UserID, YEAR(transdatetime)
Result that I got
Result that I want
I added ROW_NUMBER() into tableB, I want to SUM(Amount) WHERE MIN(ROW_NUMBER), is it impossible?
Please advise, thank you.
Based on your row_number i.e (row column of tableB) I have modified your query to take min(row) values. Please try this...If this does not work please post the complete tables structures.
SELECT UserID
,CASE WHEN COUNT(DISTINCT(b.transid )) <> 0 THEN COUNT(DISTINCT(b.transid ))
ELSE NULL END AS 'Frequency'
,SUM(Amount) as 'TotalAmount'
,YEAR(transdatetime) AS 'Year'
,SUM (CASE [Brand] WHEN 'AA' THEN 1 ELSE 0 END) AS [BrandA]
,SUM (CASE [Brand] WHEN 'BB' THEN 1 ELSE 0 END) AS [BrandB]
,SUM (CASE [Brand] WHEN 'CC' THEN 1 ELSE 0 END) AS [BrandC]
,SUM (CASE [Brand] WHEN 'DD' THEN 1 ELSE 0 END) AS [BrandD]
,SUM (CASE [Brand] WHEN 'ZZ' THEN 1 ELSE 0 END) AS [BrandZ]
FROM tableA a
INNER JOIN tableB b ON a.transid = b.transid
WHERE is_paid = 'N' AND b.row in (select min(row) from tableB group by transid)
GROUP BY UserID, YEAR(transdatetime)

Why does this query have two selects?

I have this query :
SELECT WorkId, RegisterDate, sum(RoomType1) As RoomType1, sum(RoomType2) As RoomType2, sum(RoomType3) As RoomType3, sum(RoomType4) As RoomType4, sum(RoomType5) As RoomType5, sum(RoomType6) As RoomType6, sum(RoomType7) As RoomType7, sum(RoomType8) As RoomType8
FROM (
SELECT dbo.[Work].WorkId, dbo.[Work].RegisterDate,
case dbo.Floor.RoomType when 1 then 1 else 0 end as RoomType1,
case dbo.Kat.RoomType when 2 then 1 else 0 end as RoomType2,
FROM dbo.Belediye INNER JOIN
dbo.[Is] ON dbo.Municipality.MunicipalityId= dbo.[Is].MunicipalityWorkId INNER JOIN
dbo.Look ON dbo.[Work].LookWorkId = dbo.Look.LookId ,
WHERE (dbo.Look.LocationIS NOT NULL)
) E
GROUP BY WorkId,
This query works as expected, but I can't understand why it has two selects, why does it need them? Please explain it to me. Thanks.
As you suspected this query dont need two selects and could be rewritten without sub-query:
SELECT i.IsId,
i.KayitTarihi,
SUM(case k.OdaTipi when 1 then 1 else 0 end) as RoomType1,
SUM(case k.OdaTipi when 2 then 1 else 0 end) as RoomType2,
SUM(case k.OdaTipi when 3 then 1 else 0 end) as RoomType3,
SUM(case k.OdaTipi when 4 then 1 else 0 end) as RoomType4,
SUM(case k.OdaTipi when 5 then 1 else 0 end) as RoomType5,
SUM(case k.OdaTipi when 6 then 1 else 0 end) as RoomType6,
SUM(case k.OdaTipi when 7 then 1 else 0 end) as RoomType7,
SUM(case k.OdaTipi when 8 then 1 else 0 end) as RoomType8
FROM dbo.Belediye b
INNER JOIN dbo.[Is] i
ON b.BelediyeId = i.BelediyeIsId
INNER JOIN dbo.YerGorme yg
ON i.YerGormeIsId = yg.YerGormeId
INNER JOIN dbo.Kat k
ON yg.YerGormeId = k.YerGorme_YerGormeId
WHERE yg.Lokasyon IS NOT NULL
GROUP BY i.IsId, i.KayitTarihi
Note: use table aliases