ob_clean();
    header('Content-Type: application/pdf');
    header('Content-Disposition: attachment; filename="' . basename($path) . '"');

// header('Content-Disposition: inline; filename="file.pdf"');

    header('Content-Transfer-Encoding: binary');
    header('Accept-Ranges: bytes');
    readfile($path);
    exit;

如果你想按某个字段(如customer_id)分组,并且只选择每个组的最新记录,你可以使用GROUP BY结合子查询和ORDER BY以及LIMIT来实现。

以下是一个具体的例子,假设你有一个名为orders的表,包含customer_id、order_date和order_amount三个字段,你想按customer_id分组并只获取每个客户的最新订单:

sql
SELECT customer_id, order_date, order_amount
FROM (

SELECT customer_id, order_date, order_amount,  
       ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY order_date DESC) as rn  
FROM orders  

) as subquery
WHERE rn = 1;
在这个查询中,我们使用了窗口函数ROW_NUMBER()来为每个customer_id分组内的记录分配一个行号。PARTITION BY customer_id确保行号是在每个customer_id的分组内重新开始计算的,而ORDER BY order_date DESC则确保最新的订单(即日期最晚的订单)被赋予行号1。

外部查询则选择了子查询中行号为1的记录,这样就只包含了每个客户的最新订单。

如果你的数据库不支持窗口函数,你也可以使用自连接和分组的方法来实现类似的效果:

sql
SELECT o1.customer_id, o1.order_date, o1.order_amount
FROM orders o1
LEFT JOIN orders o2

ON o1.customer_id = o2.customer_id AND o1.order_date < o2.order_date  

WHERE o2.order_date IS NULL;
在这个查询中,我们通过左连接orders表到它自己,基于customer_id和order_date来找出每个客户的最新订单。左连接会保留左表(o1)的所有记录,而WHERE子句中的o2.order_date IS NULL条件则确保只选择了在右表(o2)中没有找到更晚日期记录的记录,即每个客户的最新订单。

这两种方法都可以实现按客户分组并选择每个客户的最新订单的目的。选择哪种方法取决于你的数据库是否支持窗口函数以及你的个人偏好。

字符 含义 示例
表示日期
d 一个月中的第几天,补零 01到31
D 星期几,缩写 Mon到Sun
j 一个月中的第几天,不补零 1到31
l
(小写的’L’) 星期几,全称 Sunday到Saturday
N ISO-8601标准下,一周中的第几天 1(星期一)到7(星期天)
S 日期的序号后缀,两个字母 st,nd,rd 或th
w 一周中的第几天 0(星期天)到6(星期六)
z 一年中的第几天 0到365
表示周
W ISO-8601标准下(以周一为一周的开始),一年中的第几周 42(一年中的第42周)
表示月
F 月份,全称 January到December
m 月份,两位数字,补零 01到12
M 月份,简称,三个字母 Jan到Dec
n 月份,数字,不补零 1到12
t 一个月中的第几天 28到31
表示年
L 是否为闰年 1(闰年)0(非闰年)
o ISO-8601标准下年份,四位数字(同Y,如果W属于前一年或后一年则使用这个符号) 1999或2003
Y 年份,四位数字 1999或2003
y 年份,两位数字 99或03
表时间
a 小写的am和pm am或pm
A 大写的AM和PM AM或PM
B 国际网络时(Swatch Internet Time) 000到999
g 12小时制,小时,不补零 1到12
G 24小时制,小时,不补零 0到23
h 12小时制,小时,补零 01到12
H 24小时制,小时,补零 00到23
i 分钟,补零 00到59
s 秒,补零 00到59
u 微秒 654321
v 毫秒 654
表时区
e 时区标识符 UTC,GMT,Atlantic/Arozes
I
(大写的i) 是否为夏令时 1(夏令时)0(非夏令时)
O 与格林威治时间 (GMT) 的小时和分钟之间的差值,无冒号 +02 00
P 与格林威治时间 (GMT) 的小时和分钟之间的差值,有冒号 +02:00
T 时区缩写 EST,MDT
Z 时区偏移量(以秒为单位)。UTC 以西时区的偏移量始终为负数,而 UTC 以东的时区的偏移量始终为正值。 -43200到50400
标准格式
c ISO 8601 格式日期 2004-02-12T15:19:21+00:00
r RFC 2822 格式日期 Thu, 21 Dec 2000 16:01:07 +0200
U 自Unix时间戳(January 1 1970 00:00:00 GMT)以来的秒数

DROP PROCEDURE
IF EXISTS test_data_subject;

DELIMITER $$
CREATE PROCEDURE test_data_subject()
BEGIN

-- 定义变量
DECLARE i INT UNSIGNED DEFAULT 175;  -- 1是变量可以写10000
-- 循环次数
WHILE i <= 214 DO                                        -- i是变量可以 <10000

insert into intelligencevillage.renthouse_new_examination_subject (examination_id,subject_id) VALUES (28,i);

    SELECT i;
    SET i = i+1;
END WHILE;

END $$

CALL test_data_subject();