【问题标题】:How to efficiently select aggregate SUM value from an INNER JOINed table?如何有效地从 INNER JOINed 表中选择聚合 SUM 值?
【发布时间】:2020-08-24 18:23:24
【问题描述】:

我有一个带有状态列的子表。当我从父表中选择列时,我还想报告基于子表中所有相关行的计算状态。状态的计算非常简单:如果相关子表行中的所有状态都为 0,则查询中的状态将被设置为 0。否则,状态将被设置为非零值(并不重要)实际值为)。

我的查询实现(如下所示)在相关子行上使用 SUM()。这种方法效果很好。但是,由于 SUM(),我需要对从其他两个表中选择的所有列进行 GROUP BY。

有没有更好的方法来做到这一点?按这么多列分组时我应该担心性能吗?

顺便说一句,示例中省略了键、索引和关系。

示例表和存储过程:

CREATE DATABASE Test
GO

USE [Test]
GO

CREATE TABLE [dbo].[Customer]
(
    [CustomerId] [bigint] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](128) NOT NULL,
    [PhoneNumber] [varchar](50) NOT NULL
)
GO

CREATE TABLE [dbo].[Order]
(
    [OrderId] [bigint] IDENTITY(1,1) NOT NULL,
    [CustomerId] [bigint] NOT NULL,
    [Description1] [nvarchar](256) NOT NULL,
    [Description2] [nvarchar](26) NOT NULL,
    [Description3] [nvarchar](256) NOT NULL,
    [Date] [datetime] NOT NULL,
    [Amount] [decimal](9, 2) NOT NULL,
    [RecommendedBy] [nvarchar](50) NOT NULL
)
GO

CREATE TABLE [dbo].OrderItem
(
    [OrderId] [bigint] NOT NULL,
    [Description] [nvarchar](50) NOT NULL,
    [Status] [tinyint] NOT NULL
) 
GO

CREATE PROCEDURE [dbo].[uspSelectInvoiceSubmissionRecords]
    @CustomerId bigint
AS
BEGIN
    SET NOCOUNT ON;

    SELECT
        c.Name
        , c.PhoneNumber
        , o.OrderId
        , o.Description1
        , o.Description2
        , o.Description3
        , o.[Date]
        , o.Amount
        , o.[RecommendedBy]
        , SUM(i.Status) AS [ItemStatus]
    FROM [Order] o
    INNER JOIN OrderItem i ON i.OrderId = o.OrderId
    INNER JOIN [Customer] c ON c.CustomerId = o.CustomerId
    WHERE o.CustomerId = @CustomerId
    GROUP BY c.Name, c.PhoneNumber, o.OrderId, o.Description1, o.Description2, o.Description3, o.Date, o.Amount, o.RecommendedBy;
END

【问题讨论】:

  • 不要尝试过早优化。一些注意事项 - 此查询是否会频繁执行(按原样执行且无需进一步过滤)?不知何故,我怀疑它不是。但这有一种气味。通常,在订单处理系统中,在“关闭”(或“发货”或您的组织使用的任何术语)时,出于一般(或日常)考虑而订购“年龄”。那是你真正想做的吗?

标签: sql sql-server


【解决方案1】:

您可能会发现使用相关子查询可以提供更好的性能:

SELECT c.Name, c.PhoneNumber, o.OrderId, o.Description1, o.Description2, o.Description3,
       o.[Date], o.Amount, o.[RecommendedBy]
       (SELECT SUM(i.Status)
        FROM OrderItem i
        WHERE i.OrderId = o.OrderId
       ) AS [ItemStatus]
FROM [Order] o JOIN
     [Customer] c
     ON c.CustomerId = o.CustomerId     
WHERE o.CustomerId = @CustomerId;

对于如此少量的数据(单个客户),这可能对性能影响不大,但查询更容易维护。

【讨论】:

  • 如果只考虑状态是否为零,则可以使用 max 而不是 sum。
  • @SMor 非常好的建议。如果需要,拥有其中一种实际项目状态可能有助于故障排除。
猜你喜欢
  • 2022-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-04
  • 1970-01-01
相关资源
最近更新 更多