在结果集的第一行中选择具有空值的行集

时间:2017-07-19 07:37:22

标签: sql-server tsql

我遇到了问题。

我有一些类似的数据:

Id  Creation date       Creation date hour range    Id vehicule Id variable Value
1   2017-03-01 9:10     2017-03-01 9:00             1           6           0.18
2   2017-03-01 9:50     2017-03-01 9:00             1           3           0.50
3   2017-03-01 9:27     2017-03-01 9:00             1           3           null
4   2017-03-01 10:05    2017-03-01 10:00            1           3           0.35
5   2017-03-01 10:17    2017-03-01 10:00            1           3           0.12
6   2017-03-01 9:05     2017-03-01 9:00             1           5           0.04
7   2017-03-01 9:57     2017-03-01 9:00             1           5           null

我需要按Id vehicule选择行集组,Id变量,创建日期小时范围,按ID车辆,Id变量,第一个值为null但第二个值,第三个值,...的创建日期按组排序不是空的。因此,在上面的示例中,以下行集:

Id  Creation date       Creation date hour range    Id vehicule Id variable Value
3   2017-03-01 9:27     2017-03-01 9:00             1           3           null
2   2017-03-01 9:50     2017-03-01 9:00             1           3           0.50

你能帮我吗?

谢谢

5 个答案:

答案 0 :(得分:1)

在这种情况下,你将没有运气。我会在where子句中给出2“if exists”来过滤符合条件的所有ID:

(例如/未测试/可能需要永远)

select *
from yourTable y1
where id in

--the id must be in all IDs, where the first value of the set is null

--same ID instead of group by
(select 1 from yourTable y2 where y1.IDs = y2.IDs and  
--the first in the set
y2.createdate = (select min(createdate) from yourtable y3 with sameid) and
y2.value is null)

AND

--the id must also be in the IDs, where there are values besides the first that are not null

id in (same select but with "not min" and "not null" obviously

希望有所帮助:)

答案 1 :(得分:0)

在ORDER BY子句中包含Value字段,它将被排序到顶部,因为NULL的实用值低于非NULL值。

假设(因为您的中间段很难理解)您想要输出所有字段,但是您希望第4和第5列产生一些输出分组,每组顶部的Value = NULL:

SELECT Id, CreatedDate, CreatedDateHourRange, IdVehicule, IdVariable, Value
ORDER BY IdVehicule, IdVariable, Value

我认为不需要实际的GROUP BY子句。

我认为不清楚是否要将每个块中的NULL值行限制为只有一行NULL,但如果这样做,则需要说明日期时间列的排序顺序。

答案 2 :(得分:0)

确实分组在这里没用。此外,我不确定你的10:00记录将去哪里。这有帮助吗?

;WITH CTE_ADD_SOME_LOGIC
AS
(
SELECT Id, CreationDate         ,CreationDateHourRange      ,IdVehicle      ,IdVariable ,Value
, CASE WHEN Value IS NULL THEN 1 ELSE 0 END AS VALUE_IS_NULL FROM tbl

),
CTE_MORE_LOGIC
AS
(
SELECT Id, CreationDate         ,CreationDateHourRange      ,IdVehicle      ,IdVariable ,Value,VALUE_IS_NULL
, RANK() OVER (ORDER BY CreationDateHourRange,VALUE_IS_NULL) AS RN FROM CTE_ADD_SOME_LOGIC),
CTE_ORDER
AS
(
SELECT Id, CreationDate         ,CreationDateHourRange      ,IdVehicle      ,IdVariable ,Value,VALUE_IS_NULL, RN
, ROW_NUMBER() OVER(PARTITION BY RN ORDER BY RN,IdVehicle,IdVariable,CreationDate, VALUE_IS_NULL DESC) AS HIERARCHY  FROM CTE_MORE_LOGIC
)

SELECT Id, CreationDate         ,CreationDateHourRange      ,IdVehicle      ,IdVariable ,Value FROM CTE_ORDER WHERE HIERARCHY = 1
ORDER BY Id

答案 3 :(得分:0)

尝试此查询

DECLARE @Nulloccurrence INT=1 -- Give like 1,2,3 value to get first null occurrence 2 for 2nd null occurrence 

SELECT TOP 2 *
FROM cte
WHERE Id <= (
SELECT ID FROM
(
        SELECT  Id, ROW_NUMBER()OVER( Order by id) AS Seq   
        FROM cte
        WHERE (
                CASE 
                    WHEN CAST(variableValue AS VARCHAR) IS NULL
                        THEN 'P'
                    ELSE CAST(variableValue AS VARCHAR)
                    END
                ) = 'P'
                )Dt
                WHERE Dt.Seq=@Nulloccurrence
        )
ORDER BY 1 DESC

预期结果

Id  Creationdate    Creationdatehourrange   Ids vehicleId   variableValue
------------------------------------------------------------------------
3   2017-03-01 9:27  2017-03-01 9:00            1       3           NULL
2   2017-03-01 9:50  2017-03-01 9:00            1       3           0.50

答案 4 :(得分:0)

对于'第一个值为空但第二个值,第三个值,...不为空'的位置'我想你想要过滤在[Value] 中存在null和not null值的情况您分组的集合,决定是否过滤该分组行。这不能在标准WHERE子句上进行过滤,因为在WHERE子句中,每行都使用与该行范围相关的条件进行过滤。简单地说,除非您使用子查询,否则每个筛选的行都不能“看到”其他行。你需要使用HAVING子句(注释输出是2+空记录) 这将有效:

> DECLARE @mytbl TABLE(Id INT, [Creation date] DATETIME, [Creation date
> hour range] DATETIME, [Id veh] INT, [Id var] INT, Value INT )
> 
> INSERT INTO @mytbl VALUES (1,'2017-03-01 9:10 ','2017-03-01 9:00 ',1,
> 6, 0.18) INSERT INTO @mytbl VALUES (2,'2017-03-01 9:50 ','2017-03-01
> 9:00 ',1, 3, 0.50) INSERT INTO @mytbl VALUES (3,'2017-03-01 9:27
> ','2017-03-01 9:00 ',1, 3, NULL) INSERT INTO @mytbl VALUES
> (4,'2017-03-01 10:05','2017-03-01 10:00',1, 3, 0.35) INSERT INTO
> @mytbl VALUES (5,'2017-03-01 10:17','2017-03-01 10:00',1, 3, 0.12)
> INSERT INTO @mytbl VALUES (6,'2017-03-01 9:05 ','2017-03-01 9:00 ',1,
> 5, 0.04) INSERT INTO @mytbl VALUES (7,'2017-03-01 9:57 ','2017-03-01
> 9:00 ',1, 5, NULL)
> 
> SELECT [Id veh], [Id var],[Creation date hour range] FROM @mytbl GROUP
> BY [Id veh], [Id var],[Creation date hour range] HAVING COUNT([Id
> veh]) - COUNT(Value) = 1
> --HAVING COUNT([Id veh]) - COUNT(Value) >= 1 ORDER BY [Id veh], [Id var],[Creation date hour range]