I need filter result of a join query between two tables but I don't have a condition for the "where clause".
What I need is to filter based on id_project like this:
if id_project is equal to 24 (24 is the default project) then it should return only rows with
id_project =24. here rows 1,3...10 will be selected
if id_project is equal to 25, then I need those rows which have id_project=25 plus those rows which has " id_project=24 and not id_project 25, so rows number 2 to 11 will be selected
With this query :
SELECT tp.id_tag, tp.id_project, tp.NJTagName, tp.node_level , tl.id_level
FROM instrumentation.dbo.tag_project tp
INNER JOIN instrumentation.dbo.tag_level tl
ON tl.id_tag=tp.id_tag
//
where tl.id_level=69 and tp.node_level=1
I get this result :
How can I change my query to do this?
Thinking a little more about your request, it burns down to: For every id_tag give me the ID requested, or 24 if not available. This can be done in one query, where you use a ranking with ROW_NUMBER, in which you prefer the requested ID over the 24.
select *
from
(
select
tp.*,
row_number() over(partition by id_tag
order by case when id_project = 24 then 2 else 1 end) as rn
from tag_project tp
where id_project in (24, #REQUESTED_ID)
) ranked
where rn = 1;
Here is your original query changed accordingly:
SELECT id_tag, id_project, NJTagName, node_level, id_level
FROM
(
SELECT tp.id_tag, tp.id_project, tp.NJTagName, tp.node_level , tl.id_level
, row_number() over (partition by tp.id_tag order by case when tp.id_project = 24 then 2 else 1 end) as rn
FROM instrumentation.dbo.tag_project tp
INNER JOIN instrumentation.dbo.tag_level tl ON tl.id_tag=tp.id_tag
WHERE tl.id_level=69 AND tp.node_level=1
AND tp.id_project in (24, #REQUESTED_ID)
) ranked
WHERE rn = 1;
So depending of whether the user asks for ID 24 or not there are two different queries to execute.
Here is the query for ID 24:
select *
from tag_project
where id_project = 24;
Here is the query for #OTHERID. We use UNION ALL to combine the 24 records with the #OTHER records. And we use NOT EXISTS in order to avoid certain records.
select *
from tag_project
where id_project = #OTHERID
union all
select *
from tag_project tp
where id_project = 24
and not exists
(
select *
from tag_project tp2
where tp2.id_tag = tp.id_tag
and tp2.id_project = #OTHERID
);
You can write like this for default case pass #otherId as NULL.
SELECT tp.id_tag, tp.id_project, tp.NJTagName, tp.node_level , tl.id_level
FROM instrumentation.dbo.tag_project tp
INNER JOIN instrumentation.dbo.tag_level tl
ON tl.id_tag=tp.id_tag
where tl.id_level=69 and tp.node_level=1 AND tp.id_project = ISnull(#otherId, 24)
Use in:
SELECT tp.id_tag, tp.id_project, tp.NJTagName, tp.node_level , tl.id_level
FROM instrumentation.dbo.tag_project tp
INNER JOIN instrumentation.dbo.tag_level tl
ON tl.id_tag=tp.id_tag
//
where tl.id_level=69 and tp.node_level=1
and tp.id_project in (24, #OTHERID)
UPDATE:
If you want only one id_project instead, use can also use aggregation method.
SELECT tp.id_tag, tp.NJTagName, tp.node_level , tl.id_level
case when count(distinct tp.id_project) = 2 then #OTHERID
else 24 end as id_project
FROM instrumentation.dbo.tag_project tp
INNER JOIN instrumentation.dbo.tag_level tl
ON tl.id_tag=tp.id_tag
WHERE tl.id_level=69 and tp.node_level=1
AND tp.id_project in (24, #OTHERID)
GROUP BY tp.id_tag, tp.NJTagName, tp.node_level , tl.id_level
Related
I wrote a query , that gives me this Output :
(This is Just a sample obviously the Output Table contains 300000 rows approximatly)
And This is my Query :
proc sql;
create Table Output as
select ID_User, Division_ID, sum(conta) as Tot_Items, max(Counts) as Max_Item
from (select c.ID_User , c.Div_ID as Division_ID, ro.code as Mat, count(*) as Counts
from Ods.R_Ordini o
inner join DMC.Cust_Dupl c
on User_ID = ID_User
inner join ods.R_Nlines ro
on ro.Orders_Id = o.Id_Orders AND RO.SERVICE = 0
inner join ods.R_Mat m
on ro.Mat_Id = Id_Mat and flag = 0
group by
ID_User,
C.Division_ID,
Ro.Code
Having Counts > 1
)
group by
Id_User,
Division_ID
Order by
Tot_Item DESC
;
quit;
So , What i want is to re-write this Query , but instead of the Group by i want to use the Where Condition , (WHERE=(DIVISION_ID=3)) this is the condition.
I tried several attempts , with some i got errors , and with others i did got an output , but the output was not like the original one.
any help would be much appreciated , thank you.
The SAS data set option (where=(<where-expression>)) can only be coded adjacent to a data set name. So the option would have to be applied to the data set containing the column div_id that is the basis for computed column division_id. That would be table alias c
DMC.Cust_Dupl(where=(div_id=3)) as c
Or just use a normal SQL where clause
…
)
where division_id=3
group by …
Just use WHERE DIVISION_ID=3 before group by.
select ID_User, Division_ID, sum(conta) as Tot_Items, max(Counts) as Max_Item from (select c.ID_User , c.Div_ID as Division_ID, ro.code as Mat, count(*) as Counts from Ods.R_Ordini o inner join DMC.Cust_Dupl c on User_ID = ID_User inner join ods.R_Nlines ro on ro.Orders_Id = o.Id_Orders AND RO.SERVICE = 0 inner join ods.R_Mat m on ro.Mat_Id = Id_Mat and flag = 0 WHERE DIVISION_ID=3 group by ID_User, C.Division_ID, Ro.Code Having Counts > 1 ) group by Id_User, Division_ID Order by Tot_Item DESC
Microsoft has deprecated GROUP BY ALL and while the query might work now, I'd like to future-proof this query for future SQL upgrades.
Currently, my query is:
SELECT qt.QueueName AS [Queue] ,
COUNT ( qt.QueueName ) AS [#ofUnprocessedEnvelopes] ,
COUNT ( CASE WHEN dq.AssignedToUserID = 0 THEN 1
ELSE NULL
END
) AS [#ofUnassignedEnvelopes] ,
MIN ( dq.DocumentDate ) AS [OldestEnvelope]
FROM dbo.VehicleReg_Documents_QueueTypes AS [qt]
LEFT OUTER JOIN dbo.VehicleReg_Documents_Queue AS [dq] ON dq.QueueID = qt.QueueTypeID
WHERE dq.IsProcessed = 0
AND dq.PageNumber = 1
GROUP BY ALL qt.QueueName
ORDER BY qt.QueueName ASC;
And the resulting data set:
<table><tbody><tr><td>Queue</td><td>#ofUnprocessedEnvelopes</td><td>#ofUnassignedEnvelopes</td><td>OldestEnvelope</td></tr><tr><td>Cancellations</td><td>0</td><td>0</td><td>NULL</td></tr><tr><td>Dealer</td><td>26</td><td>17</td><td>2018-04-06</td></tr><tr><td>Matched to Registration</td><td>93</td><td>82</td><td>2018-04-04</td></tr><tr><td>New Registration</td><td>166</td><td>140</td><td>2018-03-21</td></tr><tr><td>Remaining Documents</td><td>2</td><td>2</td><td>2018-04-04</td></tr><tr><td>Renewals</td><td>217</td><td>0</td><td>2018-04-03</td></tr><tr><td>Transfers</td><td>296</td><td>245</td><td>2018-03-30</td></tr><tr><td>Writebacks</td><td>53</td><td>46</td><td>2018-04-09</td></tr></tbody></table>
I've tried various versions using CTE's and UNION's but I cannot get result set to generate correctly - the records that have no counts will not display or I will have duplicate records displayed.
Any suggestions on how to make this work without the GROUP BY ALL?
Below is one attempt where I tried a CTE with a UNION:
;WITH QueueTypes ( QueueTypeID, QueueName )
AS ( SELECT QueueTypeID ,
QueueName
FROM dbo.VehicleReg_Documents_QueueTypes )
SELECT qt.QueueName AS [Queue] ,
COUNT ( qt.QueueName ) AS [#ofUnprocessedEnvelopes] ,
COUNT ( CASE WHEN dq.AssignedToUserID = 0 THEN 1
ELSE NULL
END
) AS [#ofUnassignedEnvelopes] ,
CONVERT ( VARCHAR (8), MIN ( dq.DocumentDate ), 1 ) AS [OldestEnvelope]
FROM QueueTypes AS qt
LEFT OUTER JOIN dbo.VehicleReg_Documents_Queue AS dq ON dq.QueueID = qt.QueueTypeID
WHERE dq.IsProcessed = 0
AND dq.PageNumber = 1
GROUP BY qt.QueueName
UNION ALL
SELECT qt.QueueName AS [Queue] ,
COUNT ( qt.QueueName ) AS [#ofUnprocessedEnvelopes] ,
COUNT ( CASE WHEN dq.AssignedToUserID = 0 THEN 1
ELSE NULL
END
) AS [#ofUnassignedEnvelopes] ,
CONVERT ( VARCHAR (8), MIN ( dq.DocumentDate ), 1 ) AS [OldestEnvelope]
FROM QueueTypes AS qt
LEFT OUTER JOIN dbo.VehicleReg_Documents_Queue AS dq ON dq.QueueID = qt.QueueTypeID
GROUP BY qt.QueueName
But the results are not close to being correct:
Your current query doesn't work as it seems to work, because while you outer join table VehicleReg_Documents_Queue you dismiss all outer joined rows in the WHERE clause, so you are where you would have been with a mere inner join. You may want to consider either moving your criteria to the ON clause or make this an inner join right away.
It is also weird that you join queue type and queue not on the queue ID or the queue type ID, but on dq.QueueID = qt.QueueTypeID. That's like joining employees and addresses on employee number matching the house number. At least that's what it looks like.
(Then why does your queue type table have a queue name? Shouldn't the queue table contain the queue name instead? But this is not about your query, but about your data model.)
GROUP BY ALL means: "Please give us all QueueNames, even when the WHERE clause dismisses them. I see two possibilities for your query:
You do want an outer join actually. Then there is no WHERE clause and you can simply make this GROUP BY qt.QueueName.
You don't want an outer join. Then we want a row per QueueName in the table, which we might not get with simply changing GROUP BY ALL qt.QueueName to GROUP BY qt.QueueName.
In that second case we want all QueueNames first and outer join your query:
select
qn.QueueName AS [Queue],
q.[#ofUnassignedEnvelopes],
q.[OldestEnvelope]
FROM (select distinct QueueName from VehicleReg_Documents_QueueTypes) qn
LEFT JOIN
(
SELECT qt.QueueName,
COUNT ( qt.QueueName ) AS [#ofUnprocessedEnvelopes] ,
COUNT ( CASE WHEN dq.AssignedToUserID = 0 THEN 1
ELSE NULL
END
) AS [#ofUnassignedEnvelopes] ,
MIN ( dq.DocumentDate ) AS [OldestEnvelope]
FROM dbo.VehicleReg_Documents_QueueTypes AS [qt]
JOIN dbo.VehicleReg_Documents_Queue AS [dq] ON dq.QueueID = qt.QueueTypeID
WHERE dq.IsProcessed = 0
AND dq.PageNumber = 1
) q ON q.QueueName = qn.QueueName
GROUP BY ALL qn.QueueName
ORDER BY qn.QueueName ASC;
I think the best corollary here for a 'GROUP BY ALL' into something more ANSI compliant would be a CASE statement. Without knowing your data, it's hard to say for sure if this is 1:1, but I'm betting it's in the ballpark.
SELECT qt.QueueName AS [Queue]
,COUNT(CASE
WHEN dq.IsProcessed = 0
AND dq.PageNumber = 1
THEN qt.QueueName
END) AS [#ofUnprocessedEnvelopes]
,COUNT(CASE
WHEN dq.AssignedToUserID = 0
AND dq.IsProcessed = 0
AND dq.PageNumber = 1
THEN 1
ELSE NULL
END) AS [#ofUnassignedEnvelopes]
,MIN(CASE
WHEN dq.IsProcessed = 0
AND dq.PageNumber = 1
THEN dq.DocumentDate
END) AS [OldestEnvelope]
FROM dbo.VehicleReg_Documents_QueueTypes AS [qt]
LEFT OUTER JOIN dbo.VehicleReg_Documents_Queue AS [dq] ON dq.QueueID = qt.QueueTypeID
GROUP BY qt.QueueName
ORDER BY qt.QueueName ASC;
That's a bit uglier because every aggregate has to have the WHERE conditions inside a case statement, but at least you are future proof.
I have a query like this:
SELECT TV.Descrizione as TipoVers,
sum(ImportoVersamento) as ImpTot,
count(*) as N,
month(DataAllibramento) as Mese
FROM PROC_Versamento V
left outer join dbo.PROC_TipoVersamento TV
on V.IDTipoVersamento = TV.IDTipoVersamento
inner join dbo.PROC_PraticaRiscossione PR
on V.IDPraticaRiscossioneAssociata = PR.IDPratica
inner join dbo.DA_Avviso A
on PR.IDDatiAvviso = A.IDAvviso
where DataAllibramento between '2012-09-08' and '2012-09-17' and A.IDFornitura = 4
group by V.IDTipoVersamento,month(DataAllibramento),TV.Descrizione
order by V.IDTipoVersamento,month(DataAllibramento)
This query must always return something. If no result is produced a
0 0 0 0
row must be returned. How can I do this. Use a isnull for every selected field isn't usefull.
Use a derived table with one row and do a outer apply to your other table / query.
Here is a sample with a table variable #T in place of your real table.
declare #T table
(
ID int,
Grp int
)
select isnull(Q.MaxID, 0) as MaxID,
isnull(Q.C, 0) as C
from (select 1) as T(X)
outer apply (
-- Your query goes here
select max(ID) as MaxID,
count(*) as C
from #T
group by Grp
) as Q
order by Q.C -- order by goes to the outer query
That will make sure you have always at least one row in the output.
Something like this using your query.
select isnull(Q.TipoVers, '0') as TipoVers,
isnull(Q.ImpTot, 0) as ImpTot,
isnull(Q.N, 0) as N,
isnull(Q.Mese, 0) as Mese
from (select 1) as T(X)
outer apply (
SELECT TV.Descrizione as TipoVers,
sum(ImportoVersamento) as ImpTot,
count(*) as N,
month(DataAllibramento) as Mese,
V.IDTipoVersamento
FROM PROC_Versamento V
left outer join dbo.PROC_TipoVersamento TV
on V.IDTipoVersamento = TV.IDTipoVersamento
inner join dbo.PROC_PraticaRiscossione PR
on V.IDPraticaRiscossioneAssociata = PR.IDPratica
inner join dbo.DA_Avviso A
on PR.IDDatiAvviso = A.IDAvviso
where DataAllibramento between '2012-09-08' and '2012-09-17' and A.IDFornitura = 4
group by V.IDTipoVersamento,month(DataAllibramento),TV.Descrizione
) as Q
order by Q.IDTipoVersamento, Q.Mese
Use COALESCE. It returns the first non-null value. E.g.
SELECT COALESCE(TV.Desc, 0)...
Will return 0 if TV.DESC is NULL.
You can try:
with dat as (select TV.[Desc] as TipyDesc, sum(Import) as ToImp, count(*) as N, month(Date) as Mounth
from /*DATA SOURCE HERE*/ as TV
group by [Desc], month(Date))
select [TipyDesc], ToImp, N, Mounth from dat
union all
select '0', 0, 0, 0 where (select count (*) from dat)=0
That should do what you want...
If it's ok to include the "0 0 0 0" row in a result set that has data, you can use a union:
SELECT TV.Desc as TipyDesc,
sum(Import) as TotImp,
count(*) as N,
month(Date) as Mounth
...
UNION
SELECT
0,0,0,0
Depending on the database, you may need a FROM for the second SELECT. In Oracle, this would be "FROM DUAL". For MySQL, no FROM is necessary
I have the following query:
SELECT sum((select count(*) as itemCount) * "SalesOrderItems"."price") as amount, 'rma' as
"creditType", "Clients"."company" as "client", "Clients".id as "ClientId", "Rmas".*
FROM "Rmas" JOIN "EsnsRmas" on("EsnsRmas"."RmaId" = "Rmas"."id")
JOIN "Esns" on ("Esns".id = "EsnsRmas"."EsnId")
JOIN "EsnsSalesOrderItems" on("EsnsSalesOrderItems"."EsnId" = "Esns"."id" )
JOIN "SalesOrderItems" on("SalesOrderItems"."id" = "EsnsSalesOrderItems"."SalesOrderItemId")
JOIN "Clients" on("Clients"."id" = "Rmas"."ClientId" )
WHERE "Rmas"."credited"=false AND "Rmas"."verifyStatus" IS NOT null
GROUP BY "Clients".id, "Rmas".id;
The problem is that the table "EsnsSalesOrderItems" can have the same EsnId in different entries. I want to restrict the query to only pull the last entry in "EsnsSalesOrderItems" that has the same "EsnId".
By "last" entry I mean the following:
The one that appears last in the table "EsnsSalesOrderItems". So for example if "EsnsSalesOrderItems" has two entries with "EsnId" = 6 and "createdAt" = '2012-06-19' and '2012-07-19' respectively it should only give me the entry from '2012-07-19'.
SELECT (count(*) * sum(s."price")) AS amount
, 'rma' AS "creditType"
, c."company" AS "client"
, c.id AS "ClientId"
, r.*
FROM "Rmas" r
JOIN "EsnsRmas" er ON er."RmaId" = r."id"
JOIN "Esns" e ON e.id = er."EsnId"
JOIN (
SELECT DISTINCT ON ("EsnId") *
FROM "EsnsSalesOrderItems"
ORDER BY "EsnId", "createdAt" DESC
) es ON es."EsnId" = e."id"
JOIN "SalesOrderItems" s ON s."id" = es."SalesOrderItemId"
JOIN "Clients" c ON c."id" = r."ClientId"
WHERE r."credited" = FALSE
AND r."verifyStatus" IS NOT NULL
GROUP BY c.id, r.id;
Your query in the question has an illegal aggregate over another aggregate:
sum((select count(*) as itemCount) * "SalesOrderItems"."price") as amount
Simplified and converted to legal syntax:
(count(*) * sum(s."price")) AS amount
But do you really want to multiply with the count per group?
I retrieve the the single row per group in "EsnsSalesOrderItems" with DISTINCT ON. Detailed explanation:
Select first row in each GROUP BY group?
I also added table aliases and formatting to make the query easier to parse for human eyes. If you could avoid camel case you could get rid of all the double quotes clouding the view.
Something like:
join (
select "EsnId",
row_number() over (partition by "EsnId" order by "createdAt" desc) as rn
from "EsnsSalesOrderItems"
) t ON t."EsnId" = "Esns"."id" and rn = 1
this will select the latest "EsnId" from "EsnsSalesOrderItems" based on the column creation_date. As you didn't post the structure of your tables, I had to "invent" a column name. You can use any column that allows you to define an order on the rows that suits you.
But remember the concept of the "last row" is only valid if you specifiy an order or the rows. A table as such is not ordered, nor is the result of a query unless you specify an order by
Necromancing because the answers are outdated.
Take advantage of the LATERAL keyword introduced in PG 9.3
left | right | inner JOIN LATERAL
I'll explain with an example:
Assuming you have a table "Contacts".
Now contacts have organisational units.
They can have one OU at a point in time, but N OUs at N points in time.
Now, if you have to query contacts and OU in a time period (not a reporting date, but a date range), you could N-fold increase the record count if you just did a left join.
So, to display the OU, you need to just join the first OU for each contact (where what shall be first is an arbitrary criterion - when taking the last value, for example, that is just another way of saying the first value when sorted by descending date order).
In SQL-server, you would use cross-apply (or rather OUTER APPLY since we need a left join), which will invoke a table-valued function on each row it has to join.
SELECT * FROM T_Contacts
--LEFT JOIN T_MAP_Contacts_Ref_OrganisationalUnit ON MAP_CTCOU_CT_UID = T_Contacts.CT_UID AND MAP_CTCOU_SoftDeleteStatus = 1
--WHERE T_MAP_Contacts_Ref_OrganisationalUnit.MAP_CTCOU_UID IS NULL -- 989
-- CROSS APPLY -- = INNER JOIN
OUTER APPLY -- = LEFT JOIN
(
SELECT TOP 1
--MAP_CTCOU_UID
MAP_CTCOU_CT_UID
,MAP_CTCOU_COU_UID
,MAP_CTCOU_DateFrom
,MAP_CTCOU_DateTo
FROM T_MAP_Contacts_Ref_OrganisationalUnit
WHERE MAP_CTCOU_SoftDeleteStatus = 1
AND MAP_CTCOU_CT_UID = T_Contacts.CT_UID
/*
AND
(
(#in_DateFrom <= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateTo)
AND
(#in_DateTo >= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateFrom)
)
*/
ORDER BY MAP_CTCOU_DateFrom
) AS FirstOE
In PostgreSQL, starting from version 9.3, you can do that, too - just use the LATERAL keyword to achieve the same:
SELECT * FROM T_Contacts
--LEFT JOIN T_MAP_Contacts_Ref_OrganisationalUnit ON MAP_CTCOU_CT_UID = T_Contacts.CT_UID AND MAP_CTCOU_SoftDeleteStatus = 1
--WHERE T_MAP_Contacts_Ref_OrganisationalUnit.MAP_CTCOU_UID IS NULL -- 989
LEFT JOIN LATERAL
(
SELECT
--MAP_CTCOU_UID
MAP_CTCOU_CT_UID
,MAP_CTCOU_COU_UID
,MAP_CTCOU_DateFrom
,MAP_CTCOU_DateTo
FROM T_MAP_Contacts_Ref_OrganisationalUnit
WHERE MAP_CTCOU_SoftDeleteStatus = 1
AND MAP_CTCOU_CT_UID = T_Contacts.CT_UID
/*
AND
(
(__in_DateFrom <= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateTo)
AND
(__in_DateTo >= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateFrom)
)
*/
ORDER BY MAP_CTCOU_DateFrom
LIMIT 1
) AS FirstOE
Try using a subquery in your ON clause. An abstract example:
SELECT
*
FROM table1
JOIN table2 ON table2.id = (
SELECT id FROM table2 WHERE table2.table1_id = table1.id LIMIT 1
)
WHERE
...
I have query that work for me only when values in the StakeValue don't repeat.
Basically, I need to select maximum values from SI_STAKES table with their relations from two other tables grouped by internal type.
SELECT a.StakeValue, b.[StakeName], c.[ProviderName]
FROM SI_STAKES AS a
INNER JOIN SI_STAKESTYPES AS b ON a.[StakeTypeID] = b.[ID]
INNER JOIN SI_PROVIDERS AS c ON a.[ProviderID] = c.[ID] WHERE a.[EventID]=6
AND a.[StakeGroupTypeID]=1
AND a.StakeValue IN
(SELECT MAX(d.StakeValue) FROM SI_STAKES AS d
WHERE d.[EventID]=a.[EventID] AND d.[StakeGroupTypeID]=a.[StakeGroupTypeID]
GROUP BY d.[StakeTypeID])
ORDER BY b.[StakeName], a.[StakeValue] DESC
Results for example must be:
[ID] [MaxValue] [StakeTypeID] [ProviderName]
1 1,5 6 provider1
2 3,75 7 provider2
3 7,6 8 provider3
Thank you for your help
There are two problems to solve here.
1) Finding the max values per type. This will get the Max value per StakeType and make sure that we do the exercise only for the wanted events and group type.
SELECT StakeGroupTypeID, EventID, StakeTypeID, MAX(StakeValue) AS MaxStakeValue
FROM SI_STAKES
WHERE Stake.[EventID]=6
AND Stake.[StakeGroupTypeID]=1
GROUP BY StakeGroupTypeID, EventID, StakeTypeID
2) Then we need to get only one return back for that value since it may be present more then once.
Using the Max Value, we must find a unique row for each I usually do this by getting the Max ID is has the added advantage of getting me the most recent entry.
SELECT MAX(SMaxID.ID) AS ID
FROM SI_STAKES AS SMaxID
INNER JOIN (
SELECT StakeGroupTypeID, EventID, StakeTypeID, MAX(StakeValue) AS MaxStakeValue
FROM SI_STAKES
WHERE Stake.[EventID]=6
AND Stake.[StakeGroupTypeID]=1
GROUP BY StakeGroupTypeID, EventID, StakeTypeID
) AS SMaxVal ON SMaxID.StakeTypeID = SMaxVal.StakeTypeID
AND SMaxID.StakeValue = SMaxVal.MaxStakeValue
AND SMaxID.EventID = SMaxVal.EventID
AND SMaxID.StakeGroupTypeID = SMaxVal.StakeGroupTypeID
3) Now that we have the ID's of the rows that we want, we can just get that information.
SELECT Stakes.ID, Stakes.StakeValue, SType.StakeName, SProv.ProviderName
FROM SI_STAKES AS Stakes
INNER JOIN SI_STAKESTYPES AS SType ON Stake.[StakeTypeID] = SType.[ID]
INNER JOIN SI_PROVIDERS AS SProv ON Stake.[ProviderID] = SProv.[ID]
WHERE Stake.ID IN (
SELECT MAX(SMaxID.ID) AS ID
FROM SI_STAKES AS SMaxID
INNER JOIN (
SELECT StakeGroupTypeID, EventID, StakeTypeID, MAX(StakeValue) AS MaxStakeValue
FROM SI_STAKES
WHERE Stake.[EventID]=6
AND Stake.[StakeGroupTypeID]=1
GROUP BY StakeGroupTypeID, EventID, StakeTypeID
) AS SMaxVal ON SMaxID.StakeTypeID = SMaxVal.StakeTypeID
AND SMaxID.StakeValue = SMaxVal.MaxStakeValue
AND SMaxID.EventID = SMaxVal.EventID
AND SMaxID.StakeGroupTypeID = SMaxVal.StakeGroupTypeID
)
You can use the over clause since you're using T-SQL (hopefully 2005+):
select distinct
a.stakevalue,
max(a.stakevalue) over (partition by a.staketypeid) as maxvalue,
b.staketypeid,
c.providername
from
si_stakes a
inner join si_stakestypes b on
a.staketypeid = b.id
inner join si_providers c on
a.providerid = c.id
where
a.eventid = 6
and a.stakegrouptypeid = 1
Essentially, this will find the max a.stakevalue for each a.staketypeid. Using a distinct will return one and only one row. Now, if you wanted to include the min a.id along with it, you could use row_number to accomplish this:
select
s.id,
s.maxvalue,
s.staketypeid,
s.providername
from (
select
row_number() over (order by a.stakevalue desc
partition by a.staketypeid) as rownum,
a.id,
a.stakevalue as maxvalue,
b.staketypeid,
c.providername
from
si_stakes a
inner join si_stakestypes b on
a.staketypeid = b.id
inner join si_providers c on
a.providerid = c.id
where
a.eventid = 6
and a.stakegrouptypeid = 1
) s
where
s.rownum = 1