Php SQL返回所有时间记录中的第一个记录日期

Php SQL返回所有时间记录中的第一个记录日期,php,mysql,sql,Php,Mysql,Sql,存储所有时间记录的钓鱼数据库。但是,当有人有共同记录时,我希望将第一次捕获还原为真实记录 select * from T inner join (select Type, Name, max(TotDrams) as maxdrams from T WHERE Type='Common Bream' group by Type, Nam

存储所有时间记录的钓鱼数据库。但是,当有人有共同记录时,我希望将第一次捕获还原为真实记录

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一起使用。

在排名后按日期排序,然后按鱼名分组。看起来这样行吗

从T中选择* 内部连接选择物种、鱼名、maxTotalDrams作为来自T的maxdrams 其中,='Common Bream'按物种分组,鱼名 T.物种上的sq=sq.物种和T.FishName=sq.FishName和sq.maxdrams=T.TotalDrams
按T.FishName按等级、日期捕获ASC分组。您可以在每条鱼捕获的最早日期中添加另一个连接。比如:

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
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;

我处理这一问题的方式略有不同,与其试图将结果限制到最大值,不如排除那些没有达到最大值的结果。因此,使用类似于:

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
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;
然后可以将其放入子查询中,并将记录限制在前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;


这是最灵活的方法,如果您想添加更多规则,即如果您有两个相同的权重,并且在同一日期,您可以向子查询添加进一步的排序,例如Angler。这保证了在给定足够顺序的情况下,鱼名、鱼种和确定性结果的每个元组只能有一条记录。

没有ID列?您能给出表的样本数据吗?不,没有。我设置了一个SQL小提琴。不同的字段名称,但最终结果相同。零条目的记录也会产生这个问题,但我有一个计划。如果你看看结果,发现排名2的有三个人有着相同的记录——一个完美的问题:你能解释为什么约翰·巴德被除名吗?是不是因为你只想要他钓到的获胜的鱼,就像每人一张记录?还是其他标准?此数据集需要规范化。这很好。一个小问题,那就是日期捕捉。没有排序,我想这是因为它是一个字符串?什么排序不正确?该列是varchar可能会有问题。与我的php内容混淆!好吧,它工作得很漂亮,但有一点小麻烦,就是最早捕获的日期没有被挑选出来。2009年应该是Weezy G。我已经更新了sql FIDLE,这是不确定的-通过使用GROUP By T.FishName,您告诉MySQL您希望FishName的每个值都有一行,但是,您在ORDER By中指定的列不确定选择了GROUP By中未包含的字段的值。如果正确使用GROUP BY,则只有一个值可供选择,如果没有,则从可用值中随机选择一个值,然后根据您的排序依据对这些随机值进行排序。这是一个有很好文档记录的行为,不应该依赖这样的查询。我已经详细解释了这个扩展在使用不当时的缺点。为什么有两个内部连接。。。你就不能在第一个innerjoin中执行min date吗+1尽管它们有相同的结果,并且没有第二个内部联接,查询更干净:这个sql似乎只返回一些。有25种不同名字的普通鲷鱼。嗨。。你说得对。。我花了更多的时间在这上面,我所做的一些假设是不正确的。再加上约会是在一个varchar中,结果并不完全正确。修改后的答案应该是有效的,尽管它会让你为那些从未被抓到的鱼而受骗。@JohnRuddell-毕竟我需要第二次加入!查找最小日期时,分组不同!唯一的问题是空日期被认为比有日期的日期小。是的,我注意到了这一点,但数据有严重缺陷。由于日期存储为VARCHARs,因此也将“2013年11月30日”视为“2014年3月21日”之后的日期。在关于如何处理空日期的问题中没有任何细节的情况下,MySQL早期处理空日期的逻辑似乎与任何逻辑一样好。是的,这就是为什么我发布了一个带有日期方法转换的答案,以便op可以尝试使用它。。这真的需要正常化思维,谢谢。太棒了。我现在很高兴。还要感谢所有其他人和他们的时间。
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;