August 12, 2007 at 8:13 am
SELECT MIN(Col1) AS One, MIN(Col2) as Two ...
will return the minimum Col1 and the minimum Col2
But what I want is minimum Col2 where Col1 is minimum.
For example I have this table:
ID Col1 Col2
1 1 2
2 1 3
3 1 4
4 2 1
5 2 2
The select will return 1 1, while I'm interested in the row with the id 1, 1 2
I know how to achieve this using a subselect, but I wonder if it's possible to do it in just one select.
August 12, 2007 at 9:09 am
I can't figure out a straight select way to do this. The closest I can come with is like you said :
DECLARE @demo TABLE (ID INT NOT NULL IDENTITY(1,1), Col1 INT NOT NULL, Col2 INT NOT NULL)
INSERT INTO @demo (Col1, Col2)
SELECT 1, 2
UNION ALL
SELECT 1, 3
UNION ALL
SELECT 1, 4
UNION ALL
SELECT 2, 1
UNION ALL
SELECT 2, 2
UNION ALL
SELECT 2, 0 --testing to see if the query works all the time
SELECT * FROM @demo
SELECT MIN(Col1) AS Col1, MIN(Col2) AS Col2 FROM @demo WHERE Col1 = (SELECT MIN(Col1) FROM @demo)
But then again you'd need to join back to the base table to get the rest of the column. In all cases however, you'd ahve to do that anyways.
August 12, 2007 at 3:26 pm
Thank you for your reply. I just wanted to make sure that theres no other way, because in the real case I also have some inner joins and a where clause, that sadly I have to do for both of the selects.
August 12, 2007 at 3:45 pm
Can you post the actual query? Maybe we can figure something out with derived table or cte or??
August 12, 2007 at 3:56 pm
SELECT MIN(Kills.KillId) AS KillId, FirstKills.BossId
FROM Kills
INNER JOIN ( SELECT MIN(Date) AS Date, BossId
FROM Kills
INNER JOIN Guilds ON Guilds.GuildId = Kills.GuildId
INNER JOIN Realms ON Realms.RealmId = Guilds.RealmId
WHERE Date IS NOT NULL
AND Guilds.Faction = 'Alliance'
AND (@Zone = 'Worldwide' OR Realms.Zone = @Zone)
AND (@Language = 'Any' OR Realms.Language = @Language)
GROUP BY BossId ) FirstKills ON FirstKills.Date = Kills.Date AND FirstKills.BossId = Kills.BossId
INNER JOIN Guilds ON Guilds.GuildId = Kills.GuildId
INNER JOIN Realms ON Realms.RealmId = Guilds.RealmId
WHERE Guilds.Faction = 'Alliance'
AND (@Zone = 'Worldwide' OR Realms.Zone = @Zone)
AND (@Language = 'Any' OR Realms.Language = @Language)
GROUP BY FirstKills.BossId
That's the part of the query with the issue. It's working as intended now. I hope you can understand it
August 12, 2007 at 4:38 pm
Can you post a script to create the tables and some sample data along with the required results. Maybe there's a better way but I can't sese one at the moment... but if I had the tbales ot work with, then I could run some tests.
August 13, 2007 at 9:39 am
WOW! I'm thinking that a select top 1, where you order by in the sequence you want to control by - but what if you have more than one minimum value match? If you are only controlling to find the values, then select top 1 should work, no?
something like:
SELECT top 1 Kills.KillId AS KillId, Kills.Date, FirstKills.BossId
FROM Kills
INNER JOIN FirstKills ON FirstKills.Date = Kills.Date AND FirstKills.BossId = Kills.BossId
INNER JOIN Guilds ON Guilds.GuildId = Kills.GuildId
INNER JOIN Realms ON Realms.RealmId = Guilds.RealmId
WHERE Guilds.Faction = 'Alliance'
AND (@Zone = 'Worldwide' OR Realms.Zone = @Zone)
AND (@Language = 'Any' OR Realms.
order by Kills.Date, Kills.KillId
August 14, 2007 at 7:02 am
These are max() functions, but same thing. You may be able to do it, but will it really be more efficient?
http://www.sqlservercentral.com/forums/shwmessage.aspx?forumid=338&messageid=387101#bm389305
August 14, 2007 at 7:56 am
It is the ROW_NUMBER() example in the above link which is likely to be the most efficient. eg
SELECT D.BossID, D.KillID
FROM (
SELECT ROW_NUMBER() OVER (PARTITION BY BossID ORDER BY KillID) AS RowID
,Kills.BossId
,Kills.KillID
,Kills.[Date]
,Kills.GuildId
,Kills.RealmId
-- etc
FROM Kills
INNER JOIN Guilds ON Guilds.GuildId = Kills.GuildId
INNER JOIN Realms ON Realms.RealmId = Guilds.RealmId
WHERE Kills.[Date] IS NOT NULL
AND Guilds.Faction = 'Alliance'
AND (@Zone = 'Worldwide' OR Realms.Zone = @Zone)
AND (@Language = 'Any' OR Realms.Language = @Language)
) D
WHERE D.RowID = 1
August 14, 2007 at 11:37 am
declare @Table table (
id int primary key,
col1 int,
col2 int
);
-- Mix up the values so there is no beneficial order
insert into @Table
(id, col1, col2)
select 1, 1, 3 union all
select 2, 2, 2 union all
select 3, 1, 4 union all
select 4, 1, 2 union all
select 5, 2, 1;
select top 1 *
from @Table
group by id, col1, col2
order by col1, col2
-- Result:
-- id col1 col2
-- 4 1 2
Tomm Carr
--
Version Normal Form -- http://groups.google.com/group/vrdbms
August 15, 2007 at 11:04 am
So you want the smallest MIN(Col2) where Col1 = MIN(Col1) right?
Why not
SELECT Col1, MIN(Col2)
FROM Table
WHERE Col1 = (SELECT MIN(Col1) FROM Table)
GROUP BY Col1
August 15, 2007 at 2:08 pm
As I said I know how to do it with 2 selects, but I was wondering if its possible to do it with just one select. I have to inner join some big tables and and create a where clause, so having 2 selects means I have to do this for each select.
Now I found that theres no way to do it in 1 select, so I have to stick with the solution I already have.
Thanks for all your replies. You all were a great help and gave me some good ideas.
August 15, 2007 at 2:14 pm
Um, I did it in one select, based on the example you posted.
Tomm Carr
--
Version Normal Form -- http://groups.google.com/group/vrdbms
Viewing 13 posts - 1 through 12 (of 12 total)
You must be logged in to reply to this topic. Login to reply