sql-server - Microsoft SQL Server:选择每台机器上生产的每个零件号的前 N 个、联合和反透视
问题描述
我有两台机器,每台机器都生产相同的零件号。每台机器都有三个参数。数据存储在一行中。我想根据降序时间从每台机器上生产的每个零件编号中选择前 N 个结果(即机器 1 和 2 上生产的零件 1、2、3 和 4 的最新 5 个结果),取消旋转结果并显示他们每个都有一个新的行号。环境是 Microsoft SQL Server 2016。
样本数据:
id PartNumber WorkCenter UniquePartID Measurement1 Measurement2 Measurement3 transactionDT
--------------------------------------------------------------------------------------------------------------
1 1 1 78 24.2 20.6 24.6 2018-08-10 11:03:34.000
2 1 2 135 24.3 20.7 24.7 2018-08-10 11:03:28.000
3 2 2 45 58.7 49.9 59.6 2018-08-09 11:03:22.000
4 2 2 32 58.6 49.8 59.5 2018-08-09 11:03:16.000
5 3 1 65 42.2 35.9 42.8 2018-08-07 11:03:10.000
6 3 2 96 42.2 35.9 42.8 2018-08-07 11:03:04.000
7 4 1 12 108.2 92 109.8 2018-08-06 11:02:57.000
8 4 2 54 108.4 92.1 110.2 2018-08-06 11:02:50.000
9 1 1 77 24.2 20.6 24.6 2018-08-05 11:02:43.000
10 1 1 76 24.2 20.6 24.6 2018-08-05 11:02:36.000
所需结果的前几行:
ROWID PARTNUMBER TIMESTAMP WORKCENTER UniquePartID PARAMETER MEASUREMENT
------------------------------------------------------------------------------------------------
1 1 2018-08-10 11:03:34.000 1 78 Measurement 1 24.2
2 1 2018-08-10 11:03:34.000 1 78 Measurement 2 20.6
3 1 2018-08-10 11:03:34.000 1 78 Measurement 3 24.6
4 1 2018-08-10 11:03:28.000 2 135 Measurement 1 24.3
5 1 2018-08-05 11:02:43.000 2 135 Measurement 2 20.7
6 1 2018-08-05 11:02:36.000 2 135 Measurement 3 24.7
使用的 T-SQL 语句:
SELECT
ROW_NUMBER() OVER (ORDER BY TIMESTAMP DESC) ROWID,
*
FROM
(SELECT DISTINCT TOP 10
PartNumber AS PARTNUMBER, transactionDT AS TIMESTAMP,
CASE
WHEN WorkCenter = 1 THEN 'WC 1'
WHEN WorkCenter = 2 THEN 'WC 2'
END AS WORKCENTER,
UniquePartID, 'Measurement1' AS PARAMETER,
measurement1 AS MEASUREMENT
FROM
parts.dbo.data
UNION
SELECT DISTCINT TOP 10
PartNumber AS PARTNUMBER, transactionDT AS TIMESTAMP,
CASE
WHEN WorkCenter = 1 THEN 'WC 1'
WHEN WorkCenter = 2 THEN 'WC 2'
END AS WORKCENTER,
UniquePartID, 'Measurement2' AS PARAMETER,
measurement2 AS MEASUREMENT
FROM
parts.dbo.data
UNION
SELECT DISTCINT TOP 10
PartNumber AS PARTNUMBER, transactionDT AS TIMESTAMP,
CASE
WHEN WorkCenter = 1 THEN 'WC 1'
WHEN WorkCenter = 2 THEN 'WC 2'
END AS WORKCENTER,
UniquePartID, 'Measurement3' AS PARAMETER,
measurement3 AS MEASUREMENT
FROM
parts.dbo.data) a
ORDER BY
TIMESTAMP DESC, PARAMETER ASC
谢谢!
******更新的 t-SQL 代码
SELECT ROW_NUMBER() OVER(PARTITION BY PARTNUMBER, WORKCENTER ORDER BY
TIMESTAMP DESC) ROWID, *
FROM (
SELECT PartNumber AS PARTNUMBER, transactionDT AS TIMESTAMP, CASE
WHEN WorkCenter = 1 THEN 'Work Center 1' WHEN WorkCenter = 2 THEN 'Work
Center 2' END AS WORKCENTER, UniquePartID, 'Measurement1' AS PARAMETER,
Measurement1 AS MEASUREMENT, Measurement1Min AS
SPEC_MIN, Measurement1Nominal AS NOMINAL, Measurement1Max AS SPEC_MAX
FROM parts.dbo.data
UNION ALL
SELECT PartNumber AS PARTNUMBER, transactionDT AS TIMESTAMP, CASE
WHEN WorkCenter = 1 THEN 'Work Center 1' WHEN WorkCenter = 2 THEN 'Work
Center 2' END AS WORKCENTER, UniquePartID, 'Measurement2' AS PARAMETER,
Measurement2 AS MEASUREMENT, Measurement2Min AS
SPEC_MIN, Measurement2Nominal AS NOMINAL, Measurement2Max AS SPEC_MAX
FROM parts.dbo.data
UNION ALL
SELECT PartNumber AS PARTNUMBER, transactionDT AS TIMESTAMP, CASE WHEN
WorkCenter = 1 THEN 'Work Center 1' WHEN WorkCenter = 2 THEN 'Work
Center 2' END AS WORKCENTER, UniquePartID, 'Measurement3' AS PARAMETER,
Measurement3 AS MEASUREMENT, Measurement3Min AS
SPEC_MIN, Measurement3Nominal AS NOMINAL, Measurement3Max AS SPEC_MAX
FROM parts.dbo.data) a
order by TIMESTAMP DESC, PARAMETER ASC
挑战 - 这将为每条记录返回 3 行...我希望每个零件号/工作中心组合的前 N 个为 3 行。
解决方案
您的语句的问题是您在查询TOP 10
的每个部分都使用UNION
而不进行排序。
我猜你想要这样的东西:
SELECT ROW_NUMBER() OVER (ORDER BY transactionDT DESC, MEASUREMENT) ROWID,
PartNumber AS PARTNUMBER, transactionDT AS TIMESTAMP, WorkCenter AS WORKCENTER,
UniquePartID, PARAMETER, MEASUREMENT
FROM
(SELECT TOP (10) PartNumber, WorkCenter, UniquePartID,
transactionDT, Measurement1, Measurement2, Measurement3
FROM parts.dbo.data
ORDER BY transactionDT DESC) AS pvt
UNPIVOT (MEASUREMENT FOR PARAMETER IN (Measurement1, Measurement2, Measurement3)) AS upvt;
更新...
在将要求扩展到 4 列而不是 1 列之后,我似乎找不到与使用该UNION ALL
方法不同的方法来解决这个问题。与TOP N
我对原始问题的回答一样,ROW_NUMBER()
我对扩展要求的解决方案中的编号必须“尽早”完成,在这种情况下,这意味着它必须已经在UNION
查询的每个单独部分中进行。将在最后TOP 10
使用一个WHERE
子句找到:
WITH
NumberedRecords (ROWID, PARTNUMBER, TIMESTAMP, WORKCENTER, UniquePartID, PARAMETER, MEASUREMENT, SPEC_MIN, NOMINAL, SPEC_MAX) AS (
SELECT
ROW_NUMBER() OVER(PARTITION BY PartNumber, WorkCenter ORDER BY transactionDT DESC)
, PartNumber, transactionDT, 'Work Center ' + CAST(WorkCenter AS varchar(10)), UniquePartID
, 'Measurement 1', Measurement1, Measurement1Min, Measurement1Nominal, Measurement1Max
FROM parts.dbo.data
UNION ALL
SELECT
ROW_NUMBER() OVER(PARTITION BY PartNumber, WorkCenter ORDER BY transactionDT DESC)
, PartNumber, transactionDT, 'Work Center ' + CAST(WorkCenter AS varchar(10)), UniquePartID
, 'Measurement 2', Measurement2, Measurement2Min, Measurement2Nominal, Measurement2Max
FROM parts.dbo.data
UNION ALL
SELECT
ROW_NUMBER() OVER(PARTITION BY PartNumber, WorkCenter ORDER BY transactionDT DESC)
, PartNumber, transactionDT, 'Work Center ' + CAST(WorkCenter AS varchar(10)), UniquePartID
, 'Measurement 3', Measurement3, Measurement3Min, Measurement3Nominal, Measurement3Max
FROM parts.dbo.data
)
SELECT * FROM NumberedRecords WHERE ROWID <= 10;
简单的方法:
现在知道这将是一个带有 的查询UNION
,有一个简单的解决方案,只需对您已经执行的操作进行少量更改,这将适用于您的原始查询和更新后的查询:
在外部查询中OVER
的函数子句中,添加用于分区的字段。ROW_NUMBER
PARAMETER
当然,WHERE
最后使用一个子句:
WHERE ROWID <= 10
推荐阅读
- javascript - 给新手的 Javascript 闭包解释
- c# - itextsharp 5.5.13.2 显示匈牙利语和波兰语的问题
- flutter - Flutter GridView 项目点击动画
- build - 未找到发行版“伸展”
- java - 如何使persistence.xml中的凭据编程?
- sqlcmd - SQLCMD -L 返回空列表
- java - AbstractReqestLoggingFilter 的 afterRequest() 方法接受不完整的消息文本
- javascript - 如何在模型中添加多个项目
- jenkins - Jenkins 脚本化管道环境变量
- ajax - Socketio 轮询在 ajax 发布后获取更新的内容