SQL count conditioning without the 0 values - sql

I am trying to run a case count on SQL but I want the results without the 0 how do I do that?
Select ClubName,
ClubType,
Country,
Concat(Count(case when GameResult like 'w%' then 1 else NULL end), ' ','wins'),
Count(Case when GameResult like 'l%' then 1 end) AS Losses
from ClubDim,CountryDim,GamesFact
where ClubDim.CountryID = CountryDim.CountryID
And ClubDim.ClubID = GamesFact.ClubID
GROUP BY ClubName,ClubType,Country,GameResult
Having ClubType = 'Professional'
That's the code and I am getting a lot of zeros and my target is to count losses and wins in two separate columns

It's obviously not possible to test without sample data however you should be using sum not count here. Your having criteria should be part of the where clause as you are not filtering on an aggregate. I would also recommend using proper join syntax which has been standard since 1992! However this should give you expected results, I suspect.
Select ClubName,
ClubType,
Country,
Concat(sum(case when GameResult like 'w%' then 1 else 0 end), ' ','wins'),
Sum(Case when GameResult like 'l%' then 1 else 0 end) AS Losses
from ClubDim,CountryDim,GamesFact
where ClubDim.CountryID = CountryDim.CountryID and ClubDim.ClubID = GamesFact.ClubID
and ClubType = 'Professional'
GROUP BY ClubName,ClubType,Country,GameResult

The issue is that you have put gameResult in the group by.
More importantly, you need to learn proper, explicit, standard, readable JOIN syntax. Doing a Cartesian product and filtering in the WHERE clause is just awkward. Not using proper syntax is outdated:
select cl.ClubName, cl.ClubType, co.Country,
Concat(Count(case when g.GameResult like 'w%' then 1 else NULL end), ' ', 'wins'),
Count(Case when g.GameResult like 'l%' then 1 end) AS Losses
from ClubDim cl join
CountryDim co
on cl.CountryID = co.CountryID join
GamesFact g
on cl.ClubID = g.ClubID
where cl.ClubType = 'Professional'
group by cl.ClubName, cl.ClubType, co.Country;
In addition:
Note the use of table aliases. These should be abbreviations for the table names.
I did my best to qualify all columns, so it is clear what tables they come from. Of course, your question doesn't provide this information, so this is just guessing.
Filter before aggregating by using a WHERE clause rather than filtering after aggregating with a HAVING. Use HAVING when you want to filter on the results of aggregations (such as COUNT(*)).

You can try below query -
SELECT ClubName,
ClubType,
Country,
CASE WHEN Wins > 0 THEN CONCAT(Wins , ' wins') ELSE NULL END WINS,
loses
FROM (SELECT ClubName,
ClubType,
Country,
Count(case when GameResult like 'w%' then 1 else NULL end) AS Wins,
Count(Case when GameResult like 'l%' then 1 end) AS Losses
FROM ClubDim CLD
JOIN CountryDim COD ON CLD.CountryID = COD.CountryID
JOIN GamesFact GF ON CLD.ClubID = GF.ClubID
where ClubType = 'Professional'
GROUP BY ClubName,ClubType,Country) X;

Related

how to select in select postgresql

I have a column named jenis_kelamin I want to display the gender of male and female in a select query. I have a query like this but the data that comes out is still wrong, what is the correct way?
SELECT distinct mj.id, mj.nama_pd,
(select distinct count(jenis_layanan) from public.isian_kuis
where jenis_kelamin = 'Laki' ) as jumlah_laki,
(select distinct count(jenis_layanan)
from public.isian_kuis
where jenis_kelamin = 'Perempuan' ) as jumlah_perempuan
FROM public.master_jabatan mj
join isian_kuis ik on ik.jabatan_id = mj.id
group by mj.id,mj.nama_pd
order by mj.id;
I have an example of the image of my query, this is still wrong
The correct data is that at ID 30 it has two men and one woman, in ID 29 there is only one woman
No need to use nested select just use Group By like this:
SELECT distinct mj.id,
mj.nama_pd,
SUM(CASE WHEN jenis_kelamin = 'Laki' THEN 1 ELSE 0 end) AS jumlah_laki,
SUM(CASE WHEN jenis_kelamin = 'Perempuan' THEN 1 ELSE 0 end) AS jumlah_perempuan
FROM public.master_jabatan mj
join isian_kuis ik on ik.jabatan_id = mj.id
group by mj.id,mj.nama_pd
order by mj.id;
In Postgres, you can use conditional aggregation which looks like:
SELECT mj.id, mj.nama_pd,
COUNT(*) FILTER (WHERE jenis_kelamin = 'Laki')AS jumlah_laki,
COUNT(*) FILTER (WHERE jenis_kelamin = 'Perempuan') AS jumlah_perempuan
FROM public.master_jabatan mj JOIN
isian_kuis ik
ON ik.jabatan_id = mj.id
GROUP BY mj.id, mj.nama_pd
ORDER BY mj.id;
Note that it is very, very rare to use SELECT DISTINCT with GROUP BY. This might slow down the query. And FILTER is standard SQL so is a good way to implement this.

Convert rows into columns in sub-query

I'm trying to convert rows into columns when using this in a subquery query like:
select distinct
bqtID, bqtName, bqtCity, bqtStatus, bqtManagerName,
(select
max(case when serName = 'Capacity' then serStatus end) Capacity,
max(case when serName = 'Parking' then serStatus end) Parking
from
tblService
where
serBqtID = bqtID),
from
View_BanquetList
where
bqtID = 1
I get this error:
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.
While when I used it separately then it works:
select
max(case when serName = 'Capacity' then serStatus end) Capacity,
max(case when serName = 'Parking' then serStatus end) Parking
from
tblService
where
serBqtID = 1
Results:
Capacity Parking
-------- -------
101-200 51-100
Why is it not converting multiple rows into columns in sub-query?
You are trying to return two columns as one in the select list. That doesn't work. I'm not an expert on SQL Server, but with Oracle there would be at least three options.
Move the subselect to a with-clause and then join with it.
Use two sub-selects, one for capacity and one for parking.
Move the sub-select to the from clause and use a subselect that becomes a table, which is then joined.
I think all should work with SQL Server as well. Option 3 is closest to what you have now.
EDIT: try this:
select distinct
v.bqtID, v.bqtName, v.bqtCity, v.bqtStatus, v.bqtManagerName,
t.Capacity, t.Parking
from
(select
serBqtID,
max(case when serName = 'Capacity' then serStatus end) Capacity,
max(case when serName = 'Parking' then serStatus end) Parking
from
tblService
group by
serBqtID) t
inner join
View_BanquetList v on t.serBqtID = v.bqtID
where
v.bqtID = 1

Apply where clause within count in sql

SELECT
Rooms.Building,
Count(Rooms.Room) AS TotalApartments,
Count(Rooms.Room) AS ApartmentsOccupied
FROM
Rooms
WHERE
(((Rooms.AssetType) <> 'LC'))
GROUP BY
Rooms.Building;
I want to count Rooms.Room Where Rooms.Occupied = True (ApartmentsOccupied) but when I put this clause into my sql it also applies the where to the TotalApartments column
You can move some logic into CASE statements to do conditional summarization:
SELECT
Rooms.Building,
Count(Rooms.Room) AS TotalApartments,
Sum(CASE WHEN Rooms.Occupied = True THEN 1 ELSE 0 END) AS ApartmentsOccupied
FROM
Rooms
WHERE
(((Rooms.AssetType) <> 'LC'))
GROUP BY
Rooms.Building;
I'm not sure off the top of my head, but you might need to change that count to a SUM as well:
Sum(1) AS TotalApartments
And alternately, in some sql dialects the 'True' value is 1, so you could get away with something like this for the occupied count:
Sum(Rooms.Occupied) AS ApartmentsOccupied
You can do like this
SELECT
Building,
Count(Room) AS TotalApartments,
SUM(CASE WHEN Occupied = True THEN 1 ELSE 0 END) AS ApartmentsOccupied
FROM
Rooms
WHERE
AssetType <> 'LC'
GROUP BY
Building;

nested SQL queries on one table

I am having trouble formulating a query to get the desired output.
This query involves one table and two columns.
First column bld_stat has 4 different values Private, public, Public-Abandoned, Private-Abandoned the other column bld_type, single_flr, multi_flr, trailer, Whs.
I need to get results that look like this:
So far I can get the first two columns but after that I have not been able to logically get a query to work
SELECT bld_stat, COUNT(grade) AS single_flr
FROM (SELECT bld_stat,bld_type
FROM bld_inventory WHERE bld_type = 'single_flr') AS grade
GROUP BY bld_stat,bld_type,grade
The term you are going for is pivoting. I think this should work...no need for the subquery, and I've changed your group by to only bld_stat
SELECT bld_stat,
sum(case when bld_type = 'singl_flr' then 1 else 0 end) AS single_flr,
sum(case when bld_type = 'multi_flr' then 1 else 0 end) AS multi_flr,
sum(case when bld_type = 'trailer' then 1 else 0 end) AS trailer,
sum(case when bld_type = 'whs' then 1 else 0 end) AS WHS
FROM bld_inventory
GROUP BY bld_stat

SQL - How to count yes and no items

I am using SQL Server 2008.
I am writing a query where I need to count how many yesses (1) and how many nos (0 or NULL).
SELECT B.Brand, B.BrandID, COUNT(M.ModelID) AS TotalModels
FROM Brands B LEFT JOIN Models M ON B.BrandID = M.BrandID
GROUP BY B.Brand, B.BrandID
ORDER BY B.Brand
There's another field called IsBestValue in the Model table that will be NULL, 0, or 1. I want to be able to count TotalBestValueYes, TotalBestValueNo, and TotalBestValueNULL.
A long time ago...I use to use something like ..
(CASE WHEN IsBestValue = 1 END) // ADD ONE TO TotalBestValueYes
(CASE WHEN IsBestValue = 0 END) // ADD ONE TO TotalBestValueNo
(CASE WHEN IsBestValue = NULL END) // ADD ONE TO TotalBestValueNULL
Is using CASE in the fashion a good idea? Bad idea? Overkill?
Is there are better way to count yesses and nos and NULLs?
I don't see anything wrong with using the CASE like that if this is what you mean.
SELECT B.Brand,
B.BrandID,
COUNT(M.ModelID) AS TotalModels,
SUM((CASE WHEN M.IsBestValue = 1 THEN 1 ELSE 0 END)) TotalBestValueYes,
SUM((CASE WHEN M.IsBestValue = 0 THEN 1 ELSE 0 END)) TotalBestValueNo,
SUM((CASE WHEN M.IsBestValue IS NULL THEN 1 ELSE 0 END)) TotalBestValueNull,
FROM Brands B
LEFT JOIN Models M ON B.BrandID = M.BrandID
GROUP BY B.Brand,
B.BrandID
ORDER BY B.Brand
The is the perfect case for CASE (pun intended).
CASE is a very well optimized operator and was designed for just such a usage scenario.
The normal syntax for a conditional count is along the lines of:
SELECT SUM (CASE WHEN x=y then 1 ELSE 0 END) as 'XequalsY'
...
select count(nullif(IsBestValue, 0)) as TotalBestValueYes,
count(nullif(IsBestValue, 1)) as TotalBestValueNo,
count(case when IsBestValue is null then 1 end) as TotalBestValueNull