T-SQL GroupBy具有汇总的计数值和基于数字范围的组平均值

时间:2018-09-21 04:45:35

标签: sql-server tsql

我在两个表中都有数据,并且我试图基于范围生成摘要查询。该摘要旨在根据“ GWZones”进行分组,同时对计数值求和,并基于大于或小于3的范围显示这些值的平均值。

范围值基于水的pH值。

例如范围Filter1:<6.5 Filter2:> = 6.5 AND <8.5 Filter3:> = 8.5

第一个表('1WorksTable')包含“ GWZone”名称(例如Zone1,Zone2,Zone3(每个唯一的“ WorksID”有多个区域

WorksID GWZone
--------------
1       Zone1
2       Zone2
3       Zone2
4       Zone3
5       Zone3
6       Zone3
7       Zone3

第二张表('1phTable')包含需要计数的pH值,并在三个范围(ph <7,> = 7 pH <8.5,pH> = 8.5)之一内计算平均值。

LabResultsID    pH  WorksID
----------------------------
1               7       1
2               7       2
3               8       3
4               7       4
5               8       5
6               9       6
7              10       7

标准T-SQL分组查询根据所有值得出平均值,而忽略三个ph范围。

当前结果:

GWZone  SummedCountWorksID  AvgpH
----------------------------------
Zone1   1                   7
Zone2   2                   7.5
Zone3   4                   8.5

所需的结果是:

GWZone  SummedCountWorksID  AvgpH
----------------------------------
Zone1       1                   7
Zone2       1                   7
Zone3       1                   7
Zone2       1                   8
Zone3       1                   8
Zone3       2                   9.5

分区可能会有所帮助,或者在选择范围内选择范围的情况下。

表和我的基本查询的SQL代码是;

CREATE TABLE [dbo].[1WorksTable]
(
    [WorksID] [int] IDENTITY(1,1) NOT NULL,
    [GWZone] [nvarchar](15) NULL,

    CONSTRAINT [PK_1WorksTable] 
        PRIMARY KEY CLUSTERED ([WorksID] ASC)
) ON [PRIMARY]

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[1phTable]
(
    [LabResultsID] [int] IDENTITY(1,1) NOT NULL,
    [pH] [float] NULL,
    [WorksID] [int] NULL,

    CONSTRAINT [PK_1Zones] 
        PRIMARY KEY CLUSTERED ([LabResultsID] ASC)
) ON [PRIMARY]
GO

SET IDENTITY_INSERT [dbo].[1WorksTable] ON 
GO

INSERT [dbo].[1WorksTable] ([WorksID], [GWZone]) 
VALUES (1, N'Zone1'), (2, N'Zone2'), 
       (3, N'Zone2'), (4, N'Zone3'),
       (5, N'Zone3'), (6, N'Zone3'),
       (7, N'Zone3')
GO

SET IDENTITY_INSERT [dbo].[1WorksTable] OFF
GO

SET IDENTITY_INSERT [dbo].[1phTable] ON 
GO

INSERT [dbo].[1phTable] ([LabResultsID], [pH], [WorksID]) 
VALUES (1, 7, 1), (2, 7, 2), (3, 8, 3),
       (4, 7, 4), (5, 8, 5), (6, 9, 6), (7, 10, 7)
GO

SET IDENTITY_INSERT [dbo].[1phTable] OFF
GO

失败的分组查询如下;

SELECT        
    dbo.[1WorksTable].GWZone, 
    COUNT(dbo.[1phTable].WorksID) AS CountWorksID, 
    AVG(dbo.[1phTable].pH) AS AvgpH
FROM
    dbo.[1WorksTable] 
INNER JOIN
    dbo.[1phTable] ON dbo.[1WorksTable].WorksID = dbo.[1phTable].WorksID
GROUP BY 
    dbo.[1WorksTable].GWZone

任何可以帮助我使此查询根据需要运行的想法。

谢谢您的时间!

通过生成具有所有pH数据的基本视图,它消除了使SQL更复杂的表之间的联接的需求。

SELECT        dbo.[1WorksTable].GWZone, dbo.[1phTable].WorksID, dbo.[1phTable].pH
FROM            dbo.[1phTable] INNER JOIN
                         dbo.[1WorksTable] ON dbo.[1phTable].WorksID = dbo.[1WorksTable].WorksID
GROUP BY dbo.[1WorksTable].GWZone, dbo.[1phTable].pH, dbo.[1phTable].WorksID

部分解决方案产生组结构,并显示范围。

SELECT        TOP (100) PERCENT GWZone, pH, COUNT(WorksID) AS Observations
FROM            (SELECT        CASE WHEN pH BETWEEN 0 AND 6.5 THEN '<=6.5' WHEN pH >= 6.5 AND pH < 8.5 THEN '>=6.5 and <8.5' ELSE '>=8.5' END AS pH, WorksID, GWZone
                          FROM            dbo.ParentView) AS t
GROUP BY pH, GWZone
ORDER BY GWZone, pH

这样会产生一个结果;

Zone    pH Range    Sum(Count(WorksID)) 
Zone1   <6.5             1
Zone2   <6.5             1
Zone2   >=6.5 and <8.5   1
Zone3   <6.5             1
Zone3   >=6.5 and <8.5   1
Zone3   >=8.5            2

现在唯一缺少的是计算每一行的pH平均值。

2 个答案:

答案 0 :(得分:0)

  

我不确定您是如何根据所需结果来计算一些数字的,所以在这里我要暗中进行一些测试。希望以下查询能使您进一步了解所需结果的目标。

SELECT      [1WorksTable].GWZone, 
            COUNT(1) OVER(PARTITION BY [1WorksTable].GWZone ORDER BY [1phTable].WorksID) AS CountWorksID, 
            CAST(AVG([1phTable].pH) AS DECIMAL(10,2)) AS AvgpH
FROM        [1WorksTable] 
INNER JOIN  [1phTable] ON [1WorksTable].WorksID = [1phTable].WorksID
GROUP BY    [1WorksTable].WorksID,
            [1WorksTable].GWZone,
            [1phTable].WorksID
ORDER BY    AvgpH, 
            GWZone

答案 1 :(得分:0)

我怀疑您需要在partition by的{​​{1}}中加入一个case表达式

over() clause

此查询(根据您的示例数据)产生以下内容:

select *
      , CASE
            WHEN pH BETWEEN 0 AND 6.5 THEN '<=6.5'
            WHEN pH >= 6.5 AND pH < 8.5 THEN '>=6.5 and <8.5'
            ELSE '>=8.5'
        END AS ph_range
      , avg(pH) over(partition by GWZone, CASE
                        WHEN pH BETWEEN 0 AND 6.5 THEN 1
                        WHEN pH >= 6.5 AND pH < 8.5 THEN 2
                        ELSE 3 END) avg_pH
FROM [1WorksTable
INNER JOIN  [1phTable] ON [1WorksTable].WorksID = [1phTable].WorksID
ORDER BY pH, GWZone

我不确定您如何准确地获得所需的结果,但是如您在上面看到的,可以通过所需的范围计算平均值。

另请参阅:http://rextester.com/DRS47751