在SQl选择中仅选择一个条目为非零

时间:2014-08-28 10:08:05

标签: sql sql-server tsql select

我有一个场景,我必须从表中选择多行,我有一行记录,但状态不同, 有时我有两个相同的行,状态相同的数据<对于那种情况,我倾向于为第一次出现选择非零,并为剩余的出现设置为0。

下面是要显示的图像,我已经标记了删除线,并在剩余的事件中标记为0。

并且正文可以建议更好的SQL查询:

Image

以下是查询:对于ID = 1,状态1的值为零,但我需要先显示为常规值,然后再显示0,如果该状态再次重复。

CREATE TABLE #Temp
(ID INT,
ItemName varchar(10),
Price Money,
[Status] INT,
[Date] Datetime)


INSERT INTO #Temp VALUES(1,'ABC',10,1,'2014-08-27')
INSERT INTO #Temp VALUES(1,'ABC',10,2,'2014-08-27')
INSERT INTO #Temp VALUES(1,'ABC',10,1,'2014-08-28')
INSERT INTO #Temp VALUES(2,'DEF',25,1,'2014-08-26')
INSERT INTO #Temp VALUES(2,'DEF',25,3,'2014-08-27')
INSERT INTO #Temp VALUES(2,'DEF',25,1,'2014-08-28')
INSERT INTO #Temp VALUES(3,'GHI',30,1,'2014-08-27')


SELECT CASE WHEN Temp.Status = 1 THEN
 0
 ELSE
 Temp.Price END AS Price,
 * FROM (SELECT * FROM #Temp) Temp

 DROP TABLE #Temp

结果如下:

result

4 个答案:

答案 0 :(得分:1)

你可以试试这个:

;WITH DataSource AS
(
    SELECT RANK() OVER (PARTITION BY [ID], [ItemName], [Price], [Status] ORDER BY Date) AS [RankID]
           ,*
    FROM #Temp
)
SELECT [ID]
      ,[ItemName]
      ,IIF([RankID] = 1, [Price], 0)
      ,[Status]
      ,[Date]
FROM DataSource
ORDER BY [ID]
        ,[Date]

这是输出:

enter image description here

答案 1 :(得分:1)

您可以使用Row_Number()修改内部选择,并为RowNumber设置价格为零> 1。

SELECT CASE WHEN Temp.RowNumber > 1 THEN
 0
 ELSE
 Temp.Price END AS Price,
 * FROM (

          SELECT *,Row_Number() over (PARTITION  by ID,Status ORDER BY ID,Date) AS 'RowNumber'
          FROM #Temp

) Temp
Order by ID,Date 

答案 2 :(得分:0)

您可以使用UNION执行此操作:

SELECT * FROM #Temp t
WHERE NOT EXISTS 
   (SELECT * FROM #Temp 
    WHERE t.id = id and t.status = status and t.date < date)
UNION ALL
SELECT ID, ItemName, 0 as Price, status, date
WHERE EXISTS 
   (SELECT * FROM #Temp 
    WHERE t.id = id and t.status = status and t.date < date)

或子查询:

SELECT CASE 
     WHEN (SELECT COUNT(*) 
           FROM #Temp 
           WHERE t.id = id and t.status = status 
             and t.date > date) > 1 THEN 0 ELSE price END as NewPrice, t.* 
FROM #Temp t

或者可能是RANK()函数:

  SELECT CASE 
       WHEN RANK() OVER (PARTITION BY id, status ORDER BY date) > 1 
       THEN 0 ELSE Price END,
       t.*   
  FROM #Temp t

答案 3 :(得分:0)

请尝试以下代码。它对我有用。

CREATE TABLE #Temp
(ID INT,
ItemName varchar(10),
Price Money,
[Status] INT,
[Date] Datetime)


INSERT INTO #Temp VALUES(1,'ABC',10,1,'2014-08-27')
INSERT INTO #Temp VALUES(1,'ABC',10,2,'2014-08-27')
INSERT INTO #Temp VALUES(1,'ABC',10,1,'2014-08-28')
INSERT INTO #Temp VALUES(2,'DEF',25,1,'2014-08-26')
INSERT INTO #Temp VALUES(2,'DEF',25,3,'2014-08-27')
INSERT INTO #Temp VALUES(2,'DEF',25,1,'2014-08-28')
INSERT INTO #Temp VALUES(3,'GHI',30,1,'2014-08-27')


select *,case when a.rn=1 and status!=2 then price else 0 end as price  from 
     (select *,ROW_NUMBER() over(partition by status,date order by date asc) rn from #Temp) a 
     order by ItemName asc