按日期/小时/分钟和联接表的SQL组记录

时间:2019-02-04 03:16:34

标签: sql sql-server

给出以下2个表

TableA

|ParameterId|ParameterName|
|-----------|-------------|
|0          |Param_A      |
|1          |Param_B      |
|2          |Param_C      |
|3          |Param_D      |

TableB

|LogDateTime        |ParameterId|ParameterValue|
|-------------------|-----------|--------------|
|2019-01-29 00:00:12|0          |4             |
|2019-01-29 00:00:14|1          |2             |
|2019-01-29 00:00:17|2          |0             |
|2019-01-29 00:00:21|3          |1             |
|2019-01-30 00:01:13|0          |7             |
|2019-01-30 00:01:17|1          |3             |
|2019-01-30 00:01:22|2          |5             |
|2019-01-30 00:01:23|3          |9             |
|2019-01-31 00:02:20|0          |3             |
|2019-01-31 00:02:33|1          |0             |
|2019-01-31 00:02:41|2          |1             |
|2019-01-31 00:02:41|3          |6             |

如何按日期,小时和分钟对TableB中的数据进行分组,并与TableA结合以得到如下结果:

|LogDateTime     |Param_A|Param_B|Param_C|Param_D|
|----------------|-------|-------|-------|-------|
|2019-01-29 00:00|4      |2      |0      |1      |
|2019-01-30 00:01|7      |3      |5      |9      |
|2019-01-31 00:02|3      |0      |1      |6      |

3 个答案:

答案 0 :(得分:0)

使用CTE和数据透视表,如下所示:

with _prep as (
  select 
     LogDateTime=DateHourMinute(LogDateTime),
     ParameterName,
     ParameterValue
  from TableB b
  inner join TableA a on b.parameterID = a.parameterID
), 
select LogDateTime, Param_A,Param_B,Param_C,Param_D
 from (
  select LogDateTime, ParameterValue, ParameterName
  from _prep
) x 
pivot (
    max(ParameterValue) 
    for parameterName in (Param_A,Param_B,Param_C,Param_D)
) p

请注意,我通过使用模拟DateHourMinute省略了日期时间的联系/舍入-这部分虽然微不足道,但令人讨厌。

答案 1 :(得分:0)

您可以使用PIVOT来获得所需的输出,例如以下查询。

;WITH cte1 
     AS (SELECT B.*,P.parametername 
         FROM   @tableB B 
                INNER JOIN @tableA P 
                        ON B.parameterid = P.parameterid) 
SELECT * 
FROM   (SELECT 
       Cast(logdatetime AS SMALLDATETIME) AS logdatetime, 
       parametervalue, 
       parametername      
        FROM   cte1) AS SourceTable 
        PIVOT ( SUM(parametervalue) 
        FOR parametername IN ([Param_A],[Param_B], [Param_C],[Param_D] )) T 

Online Demo

注意::如果要在排除秒和毫秒的情况下ROUND分钟,则应遵循以下步骤。

CAST(logdatetime  AS smalldatetime)

如果您只想截断秒和毫秒,可以按照以下步骤进行更改。

CAST(DateAdd(minute, DateDiff(minute, 0, logdatetime), 0) AS smalldatetime)

如果您的TableA的值不是固定的(将来可能会有所变化),那么在这种情况下,您需要使用动态的PIVOT

如果参数是固定的,另一个更简单的解决方案类似于使用CASE WHEN进行以下查询。

 ;WITH cte 
     AS (SELECT Cast(logdatetime AS SMALLDATETIME) AS DT, 
                CASE WHEN parameterid = 0 THEN parametervalue  END  AS 'Param_A', 
                CASE WHEN parameterid = 1 THEN parametervalue  END  AS 'Param_B', 
                CASE WHEN parameterid = 2 THEN parametervalue  END  AS 'Param_C', 
                CASE WHEN parameterid = 3 THEN parametervalue  END  AS 'Param_D' 
         FROM   @TableB) 
SELECT dt                      AS LogDateTime, 
       Isnull(Sum(param_a), 0) AS Param_A, 
       Isnull(Sum(param_b), 0) AS Param_B, 
       Isnull(Sum(param_c), 0) AS Param_C, 
       Isnull(Sum(param_d), 0) AS Param_D 
FROM   cte 
GROUP  BY dt 

答案 2 :(得分:0)

一种可能的方法是旋转数据。如果参数计数是动态的,则可能需要生成动态语句。

输入:

-- Tables
CREATE TABLE #TableA (
   ParameterId int,
   ParameterName varchar(10)
)
INSERT INTO #TableA
  (ParameterId, ParameterName)
VALUES  
   (0, 'Param_A'),
   (1, 'Param_B'),
   (2, 'Param_C'),
   (3, 'Param_D')

CREATE TABLE #TableB (
   LogDateTime datetime,
   ParameterId int, 
   ParameterValue int
)   
INSERT INTO #TableB
   (LogDateTime, ParameterId, ParameterValue)
VALUES   
   ('2019-01-29T00:00:12', 0, 4),
   ('2019-01-29T00:00:14', 1, 2),
   ('2019-01-29T00:00:17', 2, 0),
   ('2019-01-29T00:00:21', 3, 1),
   ('2019-01-30T00:01:13', 0, 7),
   ('2019-01-30T00:01:17', 1, 3),
   ('2019-01-30T00:01:22', 2, 5),
   ('2019-01-30T00:01:23', 3, 9),
   ('2019-01-31T00:02:20', 0, 3),
   ('2019-01-31T00:02:33', 1, 0),
   ('2019-01-31T00:02:41', 2, 1),
   ('2019-01-31T00:02:41', 3, 6)

声明:

-- Statement   
SELECT
   -- Non-pivoted and pivoted columns
   [LogDateTime],
   [Param_A],
   [Param_B],
   [Param_C],
   [Param_D]
FROM (
    -- SELECT statement that produces the data
    SELECT 
       b.ParameterValue, 
       LEFT(CONVERT(varchar(19), b.LogDateTime, 120), 16) AS LogDateTime, 
       a.ParameterName
   FROM #TableB b
   LEFT JOIN #TableA a ON (b.ParameterID = a.ParameterID)
) d
PIVOT (
   -- Rotate data with PIVOT
   SUM ([ParameterValue])
   FOR [ParameterName] IN ([Param_A], [Param_B], [Param_C], [Param_D])
) p

输出:

LogDateTime         Param_A Param_B Param_C Param_D
2019-01-29 00:00    4       2       0       1
2019-01-30 00:01    7       3       5       9
2019-01-31 00:02    3       0       1       6