Member 12673779 Ответов: 3

Повторение идентификатора по отношению к месяцу в SQL


Привет,

Идентификатор ИНВ даты
1 0 2017/01/01
1 1 2017/02/01
1 2 2017/03/01
2 5 2016/05/01
3 10 2017/01/01
2 0 2016/04/01
5 2 2017/01/01
2 5 2017/01/01
2 2 2017/10/01

У меня есть вышеуказанные данные в моей таблице , и я хочу, чтобы вычисленное количество времени id пришло в месяц.
Мой ожидаемый результат таков

ID INV даты ExpectedResult
1 0 2017/01/01 Null
1 1 2017/02/01 1-й
1 2 2017/03/01 2-й
2 5 2016/05/01 1-й
3 10 2017/01/01 1-е
2 0 2016/04/01 Null
5 2 2017/01/01 1-й
2 5 2017/01/01 2-й
2 2 2017/10/01 3-е место

Что я уже пробовал:

Если(INV > 0) он начнет вычисление,
поскольку 1-я строка имеет нулевой inv, она показывает результат как null
2-я строка, так как id-1 пришел 1-й раз с inv > 0 должен показать результат как 1-й
тот же id-2 пришел в следующем месяце, он показывает результат как 2-й и так далее

Не могли бы вы посоветовать, как добиться этого в SQL

3 Ответов

Рейтинг:
1

Ambicaprasad Maurya

Привет,

В соответствии с моим пониманием вашего вопроса, я подготовил следующие шаги sql - запроса.
Шаг № 1. Получите ваши данные в столбец "TmpResult" в новой таблице 2 с помощью функции ROW_NUMBER(), partition by и order by из таблицы 1.
Шаг #2. Получить свой ожидаемый результат, используя таблица2 путем форматирования столбца "TmpResult".

Пожалуйста, переупорядочите имена столбцов в порядке запроса в соответствии с вашим требованием.
Я надеюсь, что этот запрос может помочь вам получить близкий результат, который вы хотите.
Спасибо.

/*
create table table1(ID int, INV int, Dates datetime)
select * from table1

insert into table1(ID, INV, Dates) values(1, 0 , 2017/01/01)
insert into table1(ID, INV, Dates) values(1, 1 , 2017/02/01)
insert into table1(ID, INV, Dates) values(1, 2 , 2017/03/01)
insert into table1(ID, INV, Dates) values(2, 5 , 2016/05/01)
insert into table1(ID, INV, Dates) values(3, 10, 2017/01/01)
insert into table1(ID, INV, Dates) values(2, 0 , 2016/04/01)
insert into table1(ID, INV, Dates) values(5, 2 , 2017/01/01)
insert into table1(ID, INV, Dates) values(2, 5 , 2017/01/01)
insert into table1(ID, INV, Dates) values(2, 2 , 2017/10/01)

select * from table1 
*/

-- Get data in second table using ROW_NUMBER, partition by and order by
select ID,INV,Dates,(ROW_NUMBER() OVER (partition by ID order by ID,INV,Dates) - 1) TmpResult into table2 from table1 order by ID,INV,Dates

select * from table2

select ID,INV,Dates,TmpResult,
	(case when TmpResult = 0 then NULL 
		else
			(case when TmpResult = 1 then '1st'
				when TmpResult = 2 then '2nd'
				when TmpResult = 3 then '3rd'
			else convert(varchar(5),TmpResult)+'th'
			end) 
	end) ExpectedResult
from table2


/*
drop table table1
drop table table2
*/


Рейтинг:
1

debasish mishra

First you need to select all the items whose Invoice or Inv!=0 and then store them in a temporary table.Then Use for loop and store the Month of date and year,ID and expected Result in 4 temp variables and insert the expected result with other 3 values in an other new temporary table(say New_temptbl) and for each row check if the stored month is greater than the earlier month and years are equal or not then increase the count of expected Result.There should be one else condition where year doesn't match and there you need to replace expected result variable with count 1.Do this until the row search ends.Then Write a union with a select statement where Inv=0;


CHill60

Причина моего голосования 1: ваше заявление "тогда используйте for loop". SQL Server устанавливается на основе. Количество раз, когда вам нужно использовать цикл, очень, очень далеко и мало между ними.
Смотрите мою статью Циклы обработки в SQL Server[^]

[no name]

Я согласен с общим табличным выражением

Рейтинг:
0

CHill60

Альтернатива, которая использует общие табличные выражения вместо временных таблиц и будет работать с числами до очень большого числа (хотя я тестировал только до 30), то есть вы получаете 21-е место вместо 21-го

;with cte as
(
	select id, INV, dates, cast(row_number() OVER (partition by id order by id, dates) as varchar(20)) as r
	from #t1 where INV <> 0
)
select t1.id, t1.inv, t1.dates,  r, 
   r + case when right(r, 1) = 1 and right(r,2) <> '11' and right(r,2) <> '12' then 'st' 
		when right(r,1) = 2 and right(r,2) <> '12' then 'nd' 
		when right(r,1) = 3 and right(r,3) <> '13' then 'rd'
			else 'th' end as ExpectedResult
from #t1 t1
LEFT OUTER JOIN cte ON t1.id = cte.id and t1.dates = cte.dates
order by id, dates