SQL Server在同一列中查询多个值

时间:2017-08-29 21:35:08

标签: sql-server

我是SQL新手所以请耐心等待!我正在尝试编写一个T-SQL查询(SSMS)来检索两个不同的最大值"数量"来自同一个"名称"的值从数据库中,以下面的格式调用它" meter_data":

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 JOINININTERSECT ...)但是对于我的生活,我无法弄清楚我哪里出错了。是否应该有另一个WHERE子句?

不要求免费的代码,但如果有人能指出我正确的方向,我将非常感激!

感谢。

2 个答案:

答案 0 :(得分: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;

您的查询无法正常工作,因为VOLTS和AMPS永远不会在同一行,因此AND始终为false。

如果你愿意的话,你可以通过窗口化东西来做一些优雅的OVER(..)分区,所以你可以考虑一下。

HTH

答案 1 :(得分: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