Reputation: 29
Guys this task just blowing my mind. I have sql view that calculates MODE but when it ties it just return first value now I need return value only when single MODE exist in other case NULL. Here is code of my VIEW
WITH cteModeGroups AS
(
SELECT
-- the partitioning dimensions:
wd.AntibioticID,
wd.SiteID,
wd.AccessionIdentity,
-- the measure:
wd.AntibioticConcentration, -- which in the result is the actual mode value, i.e. the concentration value that occurs most often in the group
wd.MICType, -- the qualifier that says =, <= or >
Max(pd.DateCreated) as MostRecentPlateRunDate,
ROW_NUMBER() OVER(PARTITION by wd.SiteID, wd.AccessionIdentity, wd.AntibioticID, wd.MICType ORDER BY count(1) desc ) AS RowNumber,
COUNT(1) as GroupCount
FROM ref.vwMicData wd
INNER JOIN [ref].[PlateData] pd on pd.ID = wd.PlateDataID
where wd.MIC = 1
and wd.bad = 0
and wd.AntibioticID > -1
group by wd.AntibioticConcentration, wd.SiteID, wd.AccessionIdentity, wd.AntibioticID, wd.MICType
)
select
cmg1.SiteID,
cmg1.AccessionIdentity,
cmg1.AntibioticID,
cmg1.AntibioticConcentration,
cmg1.MICType,
cmg1.RowNumber,
cmg1.GroupCount,
cmg1.MostRecentPlateRunDate,
plates.MicPlateCount
from cteModeGroups cmg1
left join cteModeGroups cmg2 on cmg2.SiteID=cmg1.SiteID
and cmg2.AccessionIdentity=cmg1.AccessionIdentity
and cmg2.AntibioticID=cmg1.AntibioticID
and cmg2.GroupCount > cmg1.GroupCount
left join (
select
vmd.AccessionIdentity,
vmd.AntibioticID,
count(distinct vmd.PlateDataID) as MicPlateCount
from ref.vwMICData vmd
where vmd.MIC=1
and vmd.AntibioticID > -1
and vmd.bad=0
--and vwd.BacteriaPresent = 1
--and vwd.Contaminated = 0
group by vmd.AntibioticID, vmd.AccessionIdentity
) Plates on Plates.AntibioticID = cmg1.AntibioticID and Plates.AccessionIdentity = cmg1.AccessionIdentity
where
cmg2.SiteID is null
Here is result of this query (highlighted equal groups need get NULL in this case)
thanks for any help.
Upvotes: 0
Views: 373
Reputation: 69789
You are very much over complicating this, and you have already done the hard work. Within your CTE you already calculate a row number, all you need to do is use it to remove the duplicates:
This means you can also remove your left join:
WITH cteModeGroups AS (...)
SELECT cmg1.SiteID,
cmg1.AccessionIdentity,
cmg1.AntibioticID,
cmg1.AntibioticConcentration,
cmg1.MICType,
cmg1.RowNumber,
cmg1.GroupCount,
cmg1.MostRecentPlateRunDate,
Plates.MicPlateCount
FROM cteModeGroups AS cmg1
LEFT JOIN
(
SELECT vmd.AccessionIdentity,
vmd.AntibioticID,
MicPlateCount = COUNT(DISTINCT vmd.PlateDataID)
FROM ref.vwMICData AS vmd
WHERE vmd.MIC = 1
AND vmd.AntibioticID > -1
AND vmd.bad = 0
GROUP BY
vmd.AntibioticID, vmd.AccessionIdentity
) AS Plates
ON Plates.AntibioticID = cmg1.AntibioticID
AND Plates.AccessionIdentity = cmg1.AccessionIdentity
WHERE cmg.RowNumber = 1;
Upvotes: 1
Reputation: 1270191
I can't really follow your question. But, here is the idea to attach the mode from a generic table, with NULL
if there are duplicates:
select t.*, cm.mode
from t outer apply
(select col as mode
from (select col, count(*) as cnt,
row_number() over (order by count(*) desc) as seqnum,
count(*) over (partition by count(*)) as cnt_cnt
from t
group by col
) cm
where cnt = 1 and cnt_cnt = 1
) cm;
The idea is to use window functions both to order by the count(*)
and to count the number of values with the count.
Upvotes: 1