SQL 查询建议 - 最新项目

Posted

技术标签:

【中文标题】SQL 查询建议 - 最新项目【英文标题】:SQL Query Advice - Most recent item 【发布时间】:2008-12-11 21:56:59 【问题描述】:

我有一张表格,用于存储客户销售数据(在期刊上,如报纸上)。产品按问题存储。示例

托管产品问题 数量 日期 已售出 1 123 2 12 01052008 2 234 1 5 01022008 1 123 1 5 01012008 2 444 2 3 02052008

如何为特定客户检索所有产品的最后一期(有什么更快的方法)?我可以提供 SQL Server 2000 和 2005 的示例吗?请注意,该表超过 500k 行。

谢谢

【问题讨论】:

澄清一下,sold 列是数据库中的日期类型吗? “最后一期”是什么意思? 我希望能够为每个产品获得最后一个问题编号(最近的)。 定义“近期”:较低的发行号是否会在较高的发行号之后被出售,如果是,您关心哪个? 我关心更高的问题编号,现在每年都会重复相同的问题(1-52)。 【参考方案1】:

假设“最新”是由日期(而不是问题编号)确定的,这种方法通常很快,假设索引不错:

SELECT
     T1.prodid,
     T1.issue
FROM
     Sales T1
LEFT OUTER JOIN dbo.Sales T2 ON
     T2.custid = T1.custid AND
     T2.prodid = T1.prodid AND
     T2.datesold > T1.datesold
WHERE
     T1.custid = @custid AND
     T2.custid IS NULL

处理 500k 行可能是笔记本电脑可以毫无问题地处理的事情,更不用说真正的服务器了,所以我不会为了“性能”而对数据库进行非规范化处理。不要通过在其他地方跟踪“最后售出”来增加额外的维护、不准确以及最令人头疼的问题。

编辑:我忘了提...这并没有专门处理两个问题具有相同确切日期的情况。对于这种情况,您可能需要根据您的业务规则对其进行调整。

【讨论】:

【参考方案2】:

通用 SQL; SQL Server 的语法应该没有太大的不同:

SELECT prodid, max(issue) FROM sales WHERE custid = ? GROUP BY prodid;

【讨论】:

如果速度太慢,请在 custid、prodid 和 issue 上添加索引。我认为按照这个顺序。【参考方案3】:

这是一个新项目吗?如果是这样,我会警惕像这样设置您的数据库并阅读一些关于规范化的内容,这样您最终可能会得到这样的结果:

CustID LastName FirstName
------ -------- ---------
1      Woman    Test
2      Man      Test

ProdID ProdName
------ --------
123    NY Times
234    Boston Globe

ProdID IssueID PublishDate
------ ------- -----------
123    1       12/05/2008
123    2       12/06/2008

CustID OrderID OrderDate
------ ------- ---------
1      1       12/04/2008

OrderID ProdID IssueID Quantity
------- ------ ------- --------
1       123    1       5
2       123    2       12

我必须更好地了解您的数据库才能提出更好的架构,但听起来您将太多东西构建到一个平面表中,这会导致很多问题。

【讨论】:

这是我架构的 95%。您的最后一张表是我需要为每个客户获取每个产品的最后一期的地方 非常感谢您的反馈。【参考方案4】:

如果您正在寻找最近的销售日期,也许这就是您所需要的:

SELECT prodid, issue
  FROM Sales 
WHERE custid = @custid 
      AND datesold = SELECT MAX(datesold) 
                       FROM Sales s 
                      WHERE s.prodid = Sales.prodid
                         AND s.issue = Sales.issue
                        AND s.custid = @custid 

【讨论】:

【参考方案5】:

查询现有的增长历史表太慢了!

强烈建议您创建一个新表 tblCustomerSalesLatest,其中存储每个客户的最后一个问题数据。并从那里选择。

【讨论】:

这种“优化”将导致数据库模式不再规范化。过早的优化是万恶之源。使用适当的索引,“最大/分组依据”的答案应该没问题。 它看起来像一个 olap 分析而不是一个 oltp 事务数据库,在这种情况下它必须被非规范化。 按用例!这就是客户支付的费用。干净的解决方案不是 100% 标准化的,而是快速实用的。 如果 tblCustomerSales 有 1 亿条记录怎么办?? 我正在考虑将其作为替代方案,问题是这需要一段时间才能实现。

以上是关于SQL 查询建议 - 最新项目的主要内容,如果未能解决你的问题,请参考以下文章

SQL 查询以获取特定对象的最新操作/更新

显示最新不同数据的 SQL Server 查询

在 SQL PARTITION 上选择最新项目

SQL只选择一项符合条件的项目

Mysql查询以获取给定项目编号的2个最新信息

如何仅从组中查询具有最新时间戳的文档?