存储所有时间记录的钓鱼数据库。但是,当有人有联合记录时,我想恢复到第一次捕获作为真实记录。
select *
from T
inner join (select Type,
Name,
max(TotDrams) as maxdrams
from T
WHERE Type='Common Bream'
group by Type, Name
) sq on T.Type = sq.Type
and T.Name = sq.Name
and sq.maxdrams = T.TotDrams
ORDER BY Ranking ASC
以上内容返回每个名称具有最佳捕获的所有时间记录,但是当记录是联合时,它自然会返回附加记录。我只希望将最早的日期记录包含在所有时间记录中。
有没有办法调整上面的代码来删除额外的联合记录,只挑选最早的记录?
Fishname Rank Weight Angler Date
Slimey Rank 1 2 lb 3 oz John Budd 30/11/2013
Fishy Rank 2 1 lb 15 oz Chris Clot 12/01/2009
Scales Rank 3 1 lb 12 oz John Budd 21/03/2014
Scales Rank 3 1 lb 12 oz Harry White 01/04/2002
通过上面的例子 - 这是目前正在发生的事情,我想删除John Budd的联合记录,因为它是联合的而不是原始的。
另一个注意事项: - 这个SQL将与php一起使用。
答案 0 :(得分:1)
您可以在每条鱼捕获的最早日期添加另一个连接。类似的东西:
select *
from T
inner join (select Species,
FishName,
max(TotalDrams) as maxdrams
from T
WHERE Species='Common Bream'
AND DateCaught <> ''
group by Species, FishName
) sq on T.Species = sq.Species
and T.FishName = sq.FishName
and sq.maxdrams = T.TotalDrams
inner join (select Species,
FishName,
min(DateCaught) as minDate
from T
WHERE Species='Common Bream'
AND DateCaught <> ''
group by Species, FishName
) sq2 on T.Species = sq2.Species
and T.FishName = sq2.FishName
and sq2.minDate = T.DateCaught
where T.DateCaught <> ''
ORDER BY Rank ASC
接下来,您可以将2个标准重构为单个联接:
select *
from T
inner join (select Species,
FishName,
max(TotalDrams) as maxdrams,
min(DateCaught) as minDate
from T
WHERE Species='Common Bream'
AND DateCaught <> ''
group by Species, FishName
) sq on T.Species = sq.Species
and T.FishName = sq.FishName
and sq.maxdrams = T.TotalDrams
and sq.minDate = T.DateCaught
where T.DateCaught <> ''
ORDER BY Rank ASC
编辑:
对数据结构的进一步分析表明,上面的答案并不完全正确 - 由于日期是varchar,它过滤掉了几条记录,而且对数据结构的假设也不正确。修改后的答案如下:
select distinct
T.species,
t.fishname,
t.rank,
t.pounds,
t.ounces,
t.drams,
t.totaldrams,
t.peg,
t.angler,
sq.*,
sq2.*
FROM (select Species,
FishName,
max(TotalDrams) as maxdrams
from T
WHERE Species='Common Bream'
group by Species, FishName
) sq
inner join (select Species,
FishName,
TotalDrams,
min(if(DateCaught='',STR_TO_DATE('31/12/3099','%d/%m/%Y'),STR_TO_DATE(DateCaught,'%d/%m/%Y'))) as minDate
from T
WHERE Species='Common Bream'
group by Species, FishName, TotalDrams
) sq2 on sq.Species = sq2.Species
and sq.FishName = sq2.FishName
and sq.MaxDrams = sq2.TotalDrams
inner join T on sq.species = T.species
and sq.fishname = T.fishname
and sq.maxdrams = T.totaldrams
and sq2.mindate = if(DateCaught='',STR_TO_DATE('31/12/3099','%d/%m/%Y'),STR_TO_DATE(DateCaught,'%d/%m/%Y'))
答案 1 :(得分:0)
排名后按日期排序,然后按鱼名分组。看起来有用吗?
select * from T
inner join (select Species, FishName, max(TotalDrams) as maxdrams from T
WHERE Species='Common Bream' group by Species, FishName
) sq on T.Species = sq.Species and T.FishName = sq.FishName and sq.maxdrams = T.TotalDrams
GROUP BY T.FishName ORDER BY Rank, DateCaught ASC
答案 2 :(得分:0)
我接近这个的方式略有不同,而不是试图将结果限制到最大值,我会排除不是的结果。所以使用类似的东西:
SELECT T.*
FROM T
LEFT JOIN T AS T2
ON T2.Species = T.Species
AND T2.FishName = T.FishName
AND (T2.TotalDrams < T.TotalDrams
OR (T.TotalDrams = T2.TotalDrams AND T2.DateCaught > T.DateCaught))
WHERE T.Species = 'Common Bream'
AND T2.Species IS NULL
ORDER BY T.Rank ASC;
这使用标准的LEFT JOIN/IS NULL
方法来排除相同鱼类类型的记录,并且:
TotalDrams
或强>
TotalDrams
和后来的DateCaught
<强> Example on SQL Fiddle 强>
由于MySQL实现子查询的方式,您可能会发现这比没有提供所需结果的原始查询表现更好!
修改强>
好的,新方法。我认为最好的解决方法是使用变量为每条记录存储一个新的行号,然后你可以过滤顶部1.以下将根据订购标准分配你的行号:
SELECT @r:= CASE WHEN @f = t.FishName AND @s:= t.Species
THEN @r + 1
ELSE 1
END AS RowNum,
@f:= t.FishName AS FishName,
@s:= t.Species AS Species,
t.Rank,
t.Pounds,
t.Ounces,
t.Drams,
t.TotalDrams,
t.Peg,
t.Angler,
STR_TO_DATE(IF(t.DateCaught = '', '31/12/2050', t.DateCaught), '%d/%m/%Y') AS DateCaught
FROM T
CROSS JOIN (SELECT @f:= '',@s:='', @r:= 0) AS v
ORDER BY t.FishName, t.Species, t.TotalDrams DESC, DateCaught ASC;
然后你可以把它放到子查询中,并将记录限制在前1:
SELECT *
FROM ( SELECT @r:= CASE WHEN @f = t.FishName AND @s = t.Species
THEN @r + 1
ELSE 1
END AS RowNum,
@f:= t.FishName AS FishName,
@s:= t.Species AS Species,
t.Rank,
t.Pounds,
t.Ounces,
t.Drams,
t.TotalDrams,
t.Peg,
t.Angler,
t.DateCaught
FROM T
CROSS JOIN (SELECT @f:= '',@s:='', @r:= 0) AS v
ORDER BY t.FishName, t.Species, t.TotalDrams DESC, STR_TO_DATE(IF(t.DateCaught = '', '31/12/2050', t.DateCaught), '%d/%m/%Y') ASC
) AS t
WHERE t.RowNum = 1
ORDER BY t.Rank ASC;
<强> Example on SQL Fiddle 强>
这是最灵活的方法,如果您想添加更多规则,即如果您有两个相同的权重,并且在同一日期,您可以为子查询添加进一步的排序,例如Angler
。这保证了(鱼名,物种)每个元组只有一个记录,并且给定足够的排序确定性结果。