【问题标题】:SQL Query Advice - Most recent itemSQL 查询建议 - 最新项目
【发布时间】: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)。

标签: sql sql-server


【解决方案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 亿条记录怎么办??
      • 我正在考虑将其作为替代方案,问题是这需要一段时间才能实现。
      猜你喜欢
      • 2022-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-22
      相关资源
      最近更新 更多