考虑需要显示如下数据的情况:
Parent 1 info
Child 1A info
Child 1B info
...
Parent 2 info
Child 2A info
Child 2B info
...
请注意,孩子只有一个级别,所以没有必要进入"嵌套集"在数据库级别。例如,在我当前的项目中,数据需要显示如下:
First name | Last name | City | ...
---------------------------------
John | Doe | Denver
Sales:
---------------------
Date | Total | ...
-----------------
Jan 1 | $100
Jan 15 | $200
Feb 1 | $100
Suzie | Springer | New York
Sales:
---------------------
Date | Total | ...
-----------------
...
我的问题是关于获取此页面数据所需的SQL,同时仍然通过使用LIMIT子句(或等效子句)进行分页。
在这种情况下,应该首先列出具有最新销售额的帐户,但当然每个帐户的所有销售额都要低于一年。
首先让我先问一个更简单的案例:让我们说排序顺序并不重要。然后我可以简单地通过帐户ID(简化示例)订购:
SELECT sh.account_id, a.first_name, a.last_name,
sh.sale_id, sh.total, sh.payment_time
FROM sales_header sh
JOIN account a on sh.account_id = a.account_id
WHERE a.account_type = 'parent'
ORDER BY sh.account_id
但是,当引入分页时,如何确保特定帐户的所有销售保持在一起?很难知道LIMIT应该有多大。
现在让我们添加所需的真实排序顺序:
SELECT sh.account_id, a.first_name, a.last_name,
sh.sale_id, sh.total, sh.payment_time
FROM sales_header sh
JOIN account a on sh.account_id = a.account_id
WHERE a.account_type = 'parent'
ORDER BY sh.payment_time
检索所有行时,没有问题 - 我只需运行查询,然后在我的应用程序代码中使用account_id索引结果(在本例中为PHP)。
但如果我添加LIMIT,那么我可能无法获得每个帐户的所有销售额,特别是对于既有旧销售又近期销售的帐户。
我已经提出了一个解决方案,但它相当复杂,特别是因为我处理动态查询参数而不是我在这里展示的简化版本。我的解决方案是运行两个单独的查询。
首先,获取我需要的所有帐户ID:
SELECT DISTINCT sh.account_id
FROM sales_header sh
JOIN account a on sh.account_id = a.account_id
WHERE a.account_type = 'parent'
ORDER BY sh.payment_time
LIMIT 10
然后,将ID放入名为$ account_ids的PHP数组中,然后构建返回显示页面所需的实际结果的查询:
$sql = 'SELECT sh.account_id, a.first_name, a.last_name,
sh.sale_id, sh.total, sh.payment_time
FROM sales_header sh
JOIN account a on sh.account_id = a.account_id
WHERE sh.account_id IN ('. implode(',', $account_ids). ')
ORDER BY sh.payment_time';
这当然也可以通过放置SQL的SQL在单个查询中完成 第一个查询implode()函数的位置,如:
WHERE sh.account_id IN (SELECT DISTINCT sh.account_id ... LIMIT 10)
但这引起了对子查询和数据库可移植性限制的担忧 - 我使用的框架允许您使用可移植的limit()方法设置限制 到不同的数据库,但我不确定如果我试图在子查询中使用限制它会如何反应 例如,与SQL Server一样。
所以,我真正的问题是:这是解决问题的最佳方法,还是有替代(更简单)的解决方案?你在类似的情况下做了什么?
答案 0 :(得分:1)
SELECT
sh.account_id, a.first_name, a.last_name,
sh.sale_id, sh.total, sh.payment_time
FROM
sales_header sh
inner JOIN
account a on sh.account_id = a.account_id
inner join (
SELECT sh.account_id, max(sh.payment_time) payment_time
FROM
sales_header sh
inner JOIN
account a on sh.account_id = a.account_id
WHERE a.account_type = 'parent'
group by sh.account_id
order by 2 desc
limit 10
) acs on acs.account_id = a.account_id
ORDER BY acs.payment_time desc, acs.account_id, sh.payment_time desc
我尝试使其与数据库无关,但必须在Sql Server中将limit
子句转换为select top 10
。