我有一个存储过程,它返回产品的平均发行价格。每个问题将有多行,因此我按条形码分组,以及为该问题插入一行的商店数量,并获得IssuePrice
的平均值,因为这来自用户输入:
ALTER PROCEDURE [dbo].[GetUnknownBarcodeReport]
@Status INT,@StoreTypeID INT
AS
BEGIN
SELECT COUNT(StoreCode) AS [# Stores]
,MAX(IssueName) AS IssueName
,AVG(IssuePrice) AS IssuePrice
,Barcode
,Product.EAN13 AS [Matched Product Code]
,Product.Name AS [Matched Product Name]
,Product.MainCatagory AS [Product Catagory]
FROM UnknownBarcodes
LEFT JOIN Product on LEFT(UnknownBarcodes.Barcode,13) = Product.EAN13
WHERE UnknownBarcodeStatusID = @Status
AND LEN(Barcode) >= 10
AND StoreTypeID = @StoreTypeID
GROUP BY Barcode, Product.EAN13, Product.Name, Product.MainCatagory
ORDER BY
CASE WHEN @status = 1 THEN
COUNT(StoreCode)
WHEN @status = 2 THEN
COUNT(StoreCode)
WHEN @status = 3 THEN
MAX(DateInserted)
END DESC
END
同一产品可以多次报告,因此有多行,但有时用户会输入不同的价格。如果十个用户都输入相同的条形码,并说价格是100
,那么AVG(IssuePrice)
也是100。但是,如果9输入100
,最后一行输入1
,则AVG更改为90.1
我想用MODE
的数学等价替换AVG
,这样上面的例子仍然会返回100
,因为报告的100
比任何其他值都多。这在SQL中可能吗?
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[UnknownBarcodes](
[ID] [int] IDENTITY(1,1) NOT NULL,
[StoreCode] [int] NULL,
[DateInserted] [datetime] NULL,
[StoreTypeID] [int] NULL,
[Barcode] [varchar](100) NULL,
[UnknownBarcodeStatusID] [int] NULL,
[StatusDescription] [varchar](1000) NULL,
[IssueName] [varchar](100) NULL,
[IssuePrice] [int] NULL,
[AutoReported] [bit] NULL,
CONSTRAINT [PK_UnknownBarcodes] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)
GO
SET ANSI_PADDING OFF
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Product](
[EAN13] [bigint] NOT NULL,
[Name] [varchar](250) NULL,
[MainCatagory] [varchar](100) NULL,
CONSTRAINT [PK_Product] PRIMARY KEY CLUSTERED
(
[EAN13] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)
GO
SET ANSI_PADDING OFF
GO
INSERT INTO [dbo].[UnknownBarcodes] ([StoreCode],[DateInserted],[StoreTypeID],[Barcode],[UnknownBarcodeStatusID],[StatusDescription],[IssueName],[IssuePrice],[AutoReported]) VALUES (412,2015-07-15 08:01:03.817,1,'977096171301112',3,'Scanning issues regarding the reported unknown item','ASIAN TRADER FREE TRADE',200,1)
INSERT INTO [dbo].[UnknownBarcodes] ([StoreCode],[DateInserted],[StoreTypeID],[Barcode],[UnknownBarcodeStatusID],[StatusDescription],[IssueName],[IssuePrice],[AutoReported]) VALUES (843,2015-07-15 08:01:03.817,1,'977096171301112',3,'Scanning issues regarding the reported unknown item','ASIAN TRADER FREE TRADE',10,1)
INSERT INTO [dbo].[UnknownBarcodes] ([StoreCode],[DateInserted],[StoreTypeID],[Barcode],[UnknownBarcodeStatusID],[StatusDescription],[IssueName],[IssuePrice],[AutoReported]) VALUES (860,2015-07-15 08:01:03.817,1,'977096171301112',3,'Scanning issues regarding the reported unknown item','ASIAN TRADER FREE TRADE',10,1)
INSERT INTO [dbo].[UnknownBarcodes] ([StoreCode],[DateInserted],[StoreTypeID],[Barcode],[UnknownBarcodeStatusID],[StatusDescription],[IssueName],[IssuePrice],[AutoReported]) VALUES (864,2015-07-15 08:01:03.817,1,'977096171301112',3,'Scanning issues regarding the reported unknown item','ASIAN TRADER FREE TRADE',10,1)
INSERT INTO [dbo].[UnknownBarcodes] ([StoreCode],[DateInserted],[StoreTypeID],[Barcode],[UnknownBarcodeStatusID],[StatusDescription],[IssueName],[IssuePrice],[AutoReported]) VALUES (964,2015-07-15 08:01:03.817,1,'977096171301112',3,'Scanning issues regarding the reported unknown item','ASIAN TRADER FREE TRADE',10,1)
INSERT INTO [dbo].[UnknownBarcodes] ([StoreCode],[DateInserted],[StoreTypeID],[Barcode],[UnknownBarcodeStatusID],[StatusDescription],[IssueName],[IssuePrice],[AutoReported]) VALUES (1061,2015-07-15 08:01:03.817,1,'977096171301112',3,'Scanning issues regarding the reported unknown item','ASIAN TRADER FREE TRADE',10,1)
INSERT INTO [dbo].[UnknownBarcodes] ([StoreCode],[DateInserted],[StoreTypeID],[Barcode],[UnknownBarcodeStatusID],[StatusDescription],[IssueName],[IssuePrice],[AutoReported]) VALUES (1350,2015-07-15 08:01:03.817,1,'977096171301112',3,'Scanning issues regarding the reported unknown item','ASIAN TRADER FREE TRADE',10,1)
INSERT INTO [dbo].[UnknownBarcodes] ([StoreCode],[DateInserted],[StoreTypeID],[Barcode],[UnknownBarcodeStatusID],[StatusDescription],[IssueName],[IssuePrice],[AutoReported]) VALUES (1375,2015-07-15 08:01:03.817,1,'977096171301112',3,'Scanning issues regarding the reported unknown item','ASIAN TRADER FREE TRADE',10,1)
INSERT INTO [dbo].[UnknownBarcodes] ([StoreCode],[DateInserted],[StoreTypeID],[Barcode],[UnknownBarcodeStatusID],[StatusDescription],[IssueName],[IssuePrice],[AutoReported]) VALUES (1489,2015-07-15 08:01:03.817,1,'977096171301112',3,'Scanning issues regarding the reported unknown item','ASIAN TRADER FREE TRADE',10,1)
INSERT INTO [dbo].[UnknownBarcodes] ([StoreCode],[DateInserted],[StoreTypeID],[Barcode],[UnknownBarcodeStatusID],[StatusDescription],[IssueName],[IssuePrice],[AutoReported]) VALUES (1531,2015-07-15 08:01:03.817,1,'977096171301112',3,'Scanning issues regarding the reported unknown item','ASIAN TRADER FREE TRADE',10,1)
您可以看到,上面集合的MODE应该是10
,即使其中一行的值为200
,这偏离了AVG
From: http://blogs.lessthandot.com/index.php/datamgmt/datadesign/calculating-mean-median-and-mode-with-sq/
要使用sql server计算模式,我们首先需要获得集合中每个值的计数。然后,我们需要过滤数据,以便返回与计数相等的值。
Declare @Temp Table(Id Int Identity(1,1), Data Decimal(10,5))
Insert into @Temp Values(1)
Insert into @Temp Values(2)
Insert into @Temp Values(5)
Insert into @Temp Values(5)
Insert into @Temp Values(5)
Insert into @Temp Values(6)
Insert into @Temp Values(6)
Insert into @Temp Values(6)
Insert into @Temp Values(7)
Insert into @Temp Values(9)
Insert into @Temp Values(10)
Insert into @Temp Values(NULL)
SELECT TOP 1 with ties DATA
FROM @Temp
WHERE DATA IS Not NULL
GROUP BY DATA
ORDER BY COUNT(*) DESC
在您的示例中,函数sql可以通过子查询完成:
(select top 1 IssuePrice from UnknownBarcodes barx where barx.BarCode = bar.Barcode group by barx.IssuePrice order by count(*) DESC ) IssuePrice_MODE
查询总数:
declare @Status int, @StoreTypeId int;
set @Status = 3;
set @StoreTypeId = 1;
SELECT
COUNT(bar.StoreCode) AS [# Stores]
,MAX(bar.IssueName) AS IssueName
,AVG(bar.IssuePrice) AS IssuePrice
,(select top 1 IssuePrice from UnknownBarcodes barx where barx.BarCode = bar.Barcode group by barx.IssuePrice order by count(*) DESC ) IssuePrice_MODE
,bar.Barcode
,Product.EAN13 AS [Matched Product Code]
,Product.Name AS [Matched Product Name]
,Product.MainCatagory AS [Product Catagory]
FROM UnknownBarcodes bar
LEFT JOIN Product on LEFT(bar.Barcode,13) = Product.EAN13
WHERE bar.UnknownBarcodeStatusID = @Status
AND LEN(bar.Barcode) >= 10
AND bar.StoreTypeID = @StoreTypeID
GROUP BY bar.Barcode, Product.EAN13, Product.Name, Product.MainCatagory
ORDER BY
CASE WHEN @status = 1 THEN
COUNT(bar.StoreCode)
WHEN @status = 2 THEN
COUNT(bar.StoreCode)
WHEN @status = 3 THEN
MAX(bar.DateInserted)
end
DESC
下面的查询可能对大型数据集更有效,因为它限制了必须迭代的结果
declare @Status int, @StoreTypeId int;
set @Status = 3;
set @StoreTypeId = 1;
with FirstQuery as (SELECT
*
FROM UnknownBarcodes bar
LEFT JOIN Product on LEFT(bar.Barcode,13) = Product.EAN13
WHERE bar.UnknownBarcodeStatusID = @Status
AND LEN(bar.Barcode) >= 10
AND bar.StoreTypeID = @StoreTypeID
)
select COUNT(StoreCode) AS [# Stores]
,MAX(IssueName) AS IssueName
,AVG(IssuePrice) AS IssuePrice
,Barcode
,(select top 1 IssuePrice from FirstQuery barx where barx.BarCode = FirstQuery.Barcode group by barx.IssuePrice order by count(*) DESC ) IssuePrice_MODE
,EAN13 AS [Matched Product Code]
,Name AS [Matched Product Name]
,MainCatagory AS [Product Catagory]
from FirstQuery
GROUP BY Barcode, EAN13, Name, MainCatagory
ORDER BY
CASE WHEN @status = 1 THEN
COUNT(StoreCode)
WHEN @status = 2 THEN
COUNT(StoreCode)
WHEN @status = 3 THEN
MAX(DateInserted)
END DESC
我使用内部查询来计算MODE
SELECT COUNT(StoreCode) AS [# Stores]
,MAX(IssueName) AS IssueName
,AVG(IssuePrice) AS IssuePrice,
(select top 1 issuePrice from [UnknownBarcodes] where ID = UnknownBarcodes.id group by IssuePrice having IssuePrice > 1) issuePrice_MODE
,Barcode
,Product.EAN13 AS [Matched Product Code]
,Product.Name AS [Matched Product Name]
,Product.MainCatagory AS [Product Catagory]
FROM UnknownBarcodes
LEFT JOIN Product on LEFT(UnknownBarcodes.Barcode,13) = Product.EAN13
WHERE UnknownBarcodeStatusID = 3
AND LEN(Barcode) >= 10
AND StoreTypeID = 1
GROUP BY Barcode, Product.EAN13, Product.Name, Product.MainCatagory
如何为您所追求的工作?不知道它在更大的数据集上的表现如何:
;with cte as
(
select count(1) over (partition by b.IssueName
,p.EAN13
,p.Name
,p.MainCatagory
) as [# Stores]
,b.IssueName
,b.IssuePrice
,row_number() over (partition by b.IssueName
,p.EAN13
,p.Name
,p.MainCatagory
order by count(1) desc
) as IssuePriceSort
,b.Barcode
,p.EAN13
,p.Name
,p.MainCatagory
from UnknownBarcodes as b
left join Product as p
on left(b.Barcode,13) = p.EAN13
where UnknownBarcodeStatusID = @Status
and len(Barcode) >= 10
and StoreTypeID = @StoreTypeID
group by b.Barcode
,b.IssueName
,b.IssuePrice
,p.EAN13
,p.Name
,p.MainCatagory
)
select [# Stores]
,[IssueName]
,[IssuePrice]
,[IssuePriceSort]
,[Barcode]
,[EAN13]
,[Name]
,[MainCatagory]
from cte
where IssuePriceSort = 1