2017-08-29 45 views
0

我对SQL很陌生,请耐心等待!我试图写一个T-SQL查询(SSMS)从数据库中检索两个不同的最大“数量”来自同一个“名称”值,命名为“meter_data”,在下面的格式:SQL Server查询同一列中的多个值

Name Date  Time Value Quantity 
------------------------------------------ 
Meter1 29-08-17 19:00 2.1 Amps 
Meter1 29-08-17 19:30 2.5 Amps 
Meter1 29-08-17 20:00 2.2 Amps 
Meter1 29-08-17 19:00 231 Volts 
Meter1 29-08-17 19:30 232 Volts 
Meter1 29-08-17 20:00 235 Volts 
Meter2 29-08-17 19:00 16.1 Amps 
Meter2 29-08-17 19:30 17 Amps 
Meter2 29-08-17 20:00 17.1 Amps 
Meter2 29-08-17 19:00 415 Volts 
Meter2 29-08-17 19:30 413 Volts 
Meter2 29-08-17 20:00 412 Volts 

etc... etc... etc... etc... 

查询的结果应返回以下数据:

Meter 1 
Amps 2.5 
Volts 235 

这里是我的查询:

SELECT MAX(Value) 
FROM meter_data 
WHERE Name = 'Meter1' 
    AND (Quantity = 'Amps') 
    AND (Quantity = 'Volts') 

上述结果是:

Meter1 
NULL 

查询结果是明显是不正确,因为它与两个Quantity和在一起并返回NULL值。我尝试了几种不同的方式来达到这个目的(INNER JOIN,IN,INTERSECT ...)但是对于我的生活,我无法弄清楚我要去哪里错了。是否应该有另一个WHERE子句?

没有要求免费的代码,但如果有人可以指向我在正确的方向我会很感激!

谢谢。

+1

你必须使用'组by':'SELECT名称,数量,MAX (价值)FROM meter_data GROUP BY名称,数量' – Marcelo

+0

@Marcelo你有正确的答案,但你不需要这个名字吗?选择max(value)作为最大值,从meter_data组中按数量选择数量; – markg

+0

不,我不需要结果中的名称,只是特定仪表的'Amps'和'Volts'的最大值。 – EnergyAuto

回答

1

你可以通过几种不同的方式做到这一点,这里有一个镜头。 一种方法就是这样,只是使用联合来结合到你的结果中。 (CTE的只是模仿你的表)

with x as 
(
select 'Meter1' AS METER, 2.1 AS AMOUNT ,'Amps' AS PTYPE 
union ALL 
select'Meter1', 2.5 , 'Volts' 
union ALL 
select'Meter1', 2.2 , 'Volts' 
union ALL 
select'Meter1', 231 , 'Volts' 
union ALL 
select'Meter1', 232 , 'Volts' 
union ALL 
select'Meter1', 235 , 'Volts' 
union ALL 
select'Meter2', 16.1 ,'Amps' 
union ALL 
select'Meter2', 17 ,'Amps' 
union ALL 
select'Meter2', 17.1 ,'Amps' 
union ALL 
select'Meter2' , 415 , 'Volts' 
union ALL 
select'Meter2', 413 , 'Volts' 
union ALL 
select'Meter2' , 412, 'Volts' 

) 
SELECT MAX(X.AMOUNT) AS AMOUNT, 'AMPS' FROM X WHERE X.PTYPE='AMPS' 
UNION 
SELECT MAX(X.AMOUNT) AS AMOUNT, 'VOLTS' FROM X WHERE X.PTYPE='VOLTS' 

,或者你可以做它更像是一个支点,它看起来像这样

with x as 
(
select 'Meter1' AS METER, 2.1 AS AMOUNT ,'Amps' AS PTYPE 
union ALL 
select'Meter1', 2.5 , 'Volts' 
union ALL 
select'Meter1', 2.2 , 'Volts' 
union ALL 
select'Meter1', 231 , 'Volts' 
union ALL 
select'Meter1', 232 , 'Volts' 
union ALL 
select'Meter1', 235 , 'Volts' 
union ALL 
select'Meter2', 16.1 ,'Amps' 
union ALL 
select'Meter2', 17 ,'Amps' 
union ALL 
select'Meter2', 17.1 ,'Amps' 
union ALL 
select'Meter2' , 415 , 'Volts' 
union ALL 
select'Meter2', 413 , 'Volts' 
union ALL 
select'Meter2' , 412, 'Volts' 

) 
select Max(case when X.PTYPE='AMPS' then amount end) as 'amps', 
Max(case when X.PTYPE='volts' then amount end) as 'volts' 
from x; 

您的查询不工作,因为电压和电流是从不在同一行,因此AND总是假的。

如果你想要的话,你也许可以通过窗口化的东西来做一些优雅的OVER(..)分区,所以你可以看看。

HTH

+0

谢谢!我会研究OVER子句。 UNION ALL的棘手问题是数据库中会有超过500,000行,并且2500米......并且正在增长! – EnergyAuto

+0

你不需要做任何UNION ALL,我只是在我的CTE中做了这些来模拟你粘贴到问题中的数据。你只需要看看查询的底部部分 – markg

+0

啊!仍在学习!谢谢。 – EnergyAuto

1

这里有两种不同的选择......

SET NOCOUNT ON; 

IF OBJECT_ID('tempdb..#TestData', 'U') IS NOT NULL 
DROP TABLE #TestData; 

CREATE TABLE #TestData (
    [Name] CHAR(6) NOT NULL, 
    [Date Time] DATETIME2(0) NOT NULL, 
    [Value] DECIMAL(9,1) NOT NULL , 
    Quantity VARCHAR(5) NOT NULL 
    ); 
SET DATEFORMAT 'DMY'; 
INSERT #TestData (Name, [Date Time], Value, Quantity) VALUES 
    ('Meter1', '29-08-2017 19:00', 2.1, 'Amps'), 
    ('Meter1', '29-08-2017 19:30', 2.5, 'Amps'), 
    ('Meter1', '29-08-2017 20:00', 2.2, 'Amps'), 
    ('Meter1', '29-08-2017 19:00', 231, 'Volts'), 
    ('Meter1', '29-08-2017 19:30', 232, 'Volts'), 
    ('Meter1', '29-08-2017 20:00', 235, 'Volts'), 
    ('Meter2', '29-08-2017 19:00', 16.1, 'Amps'), 
    ('Meter2', '29-08-2017 19:30', 17, 'Amps'), 
    ('Meter2', '29-08-2017 20:00', 17.1, 'Amps'), 
    ('Meter2', '29-08-2017 19:00', 415, 'Volts'), 
    ('Meter2', '29-08-2017 19:30', 413, 'Volts'), 
    ('Meter2', '29-08-2017 20:00', 412, 'Volts'); 

--=========================================================== 

-- 2 rows per meter... 
WITH 
    cte_AddRank AS (
     SELECT 
      td.Name, td.[Date Time], td.Value, td.Quantity, 
      DR = DENSE_RANK() OVER (PARTITION BY td.Name, td.Quantity ORDER BY td.Value DESC) 
     FROM 
      #TestData td 
     ) 
SELECT 
    ar.Name, ar.Quantity, ar.Value 
FROM 
    cte_AddRank ar 
WHERE 
    ar.DR = 1; 

--================================================ 

-- 1 row per meter (pivioted)... 
SELECT 
    td.Name, 
    Amps = MAX(CASE WHEN td.Quantity = 'Amps' THEN td.Value END), 
    Volts = MAX(CASE WHEN td.Quantity = 'Volts' THEN td.Value END) 
FROM 
    #TestData td 
GROUP BY 
    td.Name; 

结果...

-- 2 rows per meter... 
Name Quantity Value 
------ -------- --------------------------------------- 
Meter1 Amps  2.5 
Meter1 Volts 235.0 
Meter2 Amps  17.1 
Meter2 Volts 415.0 

-- 1 row per meter (pivioted)... 
Name Amps         Volts 
------ --------------------------------------- --------------------------------------- 
Meter1 2.5          235.0 
Meter2 17.1         415.0 
相关问题