Sorry for my English...
I Iave a table with column
project, month, year
abc 2 2017
xyz 5 2017
abc 3 2017
abc 5 2017
abc 1 2018
How can I search project abc with month = 2 year = 2017 until month = 1 year = 2018
As far as I know, SQL Server 2008 cannot use concat function
Use math comparison:
SELECT * FROM table1
WHERE (year * 12 + month) BETWEEN (2017 * 12 + 1) AND (2018 * 12 + 1)
Try this:
Select *
From YourTable
Where DATETIMEFROMPARTS(year, month, 1, 1, 1, 1, 1)
between '2017-02-01' And '2018-01-01'
I have edited the code to account for the leading zero in the month.
Declare #temp Table
(
project varchar(50),
month int,
year int
);
Insert Into #temp
(project, month, year)
Values ('abc', 2, 2017)
Insert Into #temp
(project, month, year)
Values ('xyz', 5, 2017)
Insert Into #temp
(project, month, year)
Values ('abc', 3, 2017)
Insert Into #temp
(project, month, year)
Values ('abc', 5, 2017)
Insert Into #temp
(project, month, year)
Values ('abc', 1, 2018)
Insert Into #temp
(project, month, year)
Values ('xxx', 5, 2010)
Insert Into #temp
(project, month, year)
Values ('xxx', 12, 2018)
Declare #FromYear int = 2010;
Declare #FromMonth int = 04;
Declare #ToYear int = 2018;
Declare #ToMonth int = 05;
Select *
From #temp
Where Convert(varchar, year) + right('00' + Convert(varchar, month), 2) Between '201004' and '201805'
How can I search project abc with month = 2 year = 2017 until month = 1 year = 2018
You can use
SELECT *
FROM T
WHERE (([Year] * 10) + [Month]) BETWEEN 20172 AND 20181
AND
project = 'abc';
Demo
Related
I have a table where 2 columns are called Month and Year and are both INT. I need to return all the records that are less than the date provided.
So if I pass the following parameters #Month = 8 and #Year = 2017, I would like to return all records before August 2017. What is the best way to achieve this?
SELECT * FROM testTable
WHERE year <= #Year AND
month < #Month
is my current SQL. This won't work if I need to display the record that is November 2014
Compare them as dates. Like this:
SELECT * FROM testTable
WHERE DATEFROMPARTS(year, month, 1) <= DATEFROMPARTS(#Year, #Month, 1)
Pass The Parameter as Date. Like
DECLARE #MyDate DATE = '08-01-2014'
Now you can go for either of the below
SELECT
*
FROM YourTable
WHERE CAST(ConCAT([Monnth],'-01-',[Year]) AS DATE) = #MyDate
Or
SELECT
*
FROM YourTable
WHERE [Year] = YEAR(#MyDate)
AND [Month] = MONTH(#MyDate)
You can use DATEPART function of SQL Server
SELECT * FROM testTable
WHERE YEAR<= DATEPART(yy,yourdate) AND
MONTH < DATEPART(mm,yourdate)
It would be better to convert data types and query further.
DECLARE #testtable TABLE (id INT identity(1, 1), name VARCHAR(100), year INT, month INT)
INSERT INTO #testtable (name, year, month)
SELECT 'me', '2014', 10
UNION
SELECT 'you', '2017', 08
UNION
SELECT 'us', '2015', 10
UNION
SELECT 'Him', '2017', 10
UNION
SELECT 'Her', '2018', 1
SELECT *
FROM #testtable
WHERE CONCAT (year, '-', right('00' + cast(Month AS VARCHAR(2)), 2), '-', '01')
< = '2017-08-01'
I need a help to change the Month & Year column as Date in Result.
Ex :
Table Name : AA
Month Year
4 2016
5 2015
Result Should Be:
01-04-2016
01-05-2015
I need a SQL query for this? Can any one help me out?
Try like this,
DECLARE #AA TABLE (
Month INT
,Year INT
)
INSERT INTO #AA (
Month
,Year
)
VALUES (
4
,2016
)
,(
5
,2015
)
SELECT convert(DATE, convert(VARCHAR(50), year * 10000 + month * 100 + 01)) AS DATE
FROM #AA
Try this code:
select '01-'+cast([month] as nvarchar) + '-'+cast([Year] as nvarchar)
from YourTable
Assuming int data types:
DECLARE #Month int = 4, #Year int = 2016
SELECT CAST(CAST(#Year * 10000 + #Month * 100 + 01 As char(8)) as date)
Assuming char/varchar data types:
DECLARE #MonthString varchar(2) = 4, #YearString char(4) = 2016
SELECT CAST(#YearString +'-'+ RIGHT('00' + #MonthString, 2) + '-01' as date)
Results in both cases:
2016-04-01 -- (Date data type)
Add square brackets for the reserve keywords:
DECLARE #AA TABLE ([Month] INT, [Year] INT);
INSERT INTO #AA ([Month], [Year]) VALUES
(4, 2016),
(5, 2015);
SELECT '01-' + RIGHT('00' + CAST([MONTH] AS VARCHAR), 2) + '-' + CAST([Year] AS VARCHAR)
FROM #AA
Result:
01-04-2016
01-05-2015
DECLARE #Table1 TABLE
(Month int, Year int)
;
INSERT INTO #Table1
(Month, Year)
VALUES
(4, 2016),
(5, 2015)
;
select '01'+'-'+RIGHT('000'+CAST(Month AS VARCHAR(3)),2)+'-'+CAST(Year AS VARCHAR) from #Table1
Do not do varchar convertions. Use like below
declare #t table([Month] int,[Year] int)
insert into #t
select 4, 2016 union all
select 5, 2015
select dateadd(month,month-1,dateadd(year,[year]-1900,0)) from #t
You can use concat function to acieve this
SELECT CONCAT('01-',year,'-',month) as req_date from tableName
try this:
declare #y varchar(4)='2015'
declare #m varchar(2)='5'
--try_prase is available starting sql 2012
print try_parse('01-'+#m+'-'+#y as datetime using 'en-us')
print convert(datetime,'01-'+#m+'-'+#y,121)
In one of my db table, there is a column FinalDate which will store the date and the data type is not datetime but varchar. I would like to write a query that I can select distinct FinalDate and group/display like Jun 2012, Jul 2012.
Values for the FinalDate column would be something like below:
20120213
20120225
20120218
20120306
20120320
So, how I can write a query to select distinct of the FinalDate and display them in:
Feb 2012
Mar 2012
Declare #a table (d varchar(8))
insert into #a Values ('20120213'),('20120225'),('20120218'),('20120306'),('20120320');
Select FinalDate
from
(
select Distinct
--DateName(Month,d)+' '+CAST(Datepart(yy,d) as Varchar(4)) as FinalDate
SubString(DateName(Month,d),1,3)+' '+CAST(Datepart(yy,d) as Varchar(4)) as FinalDate
,Datepart(yy,d) as yy,Datepart(mm,d) as mm
from
(Select CAST(d as datetime) as d from #a) a
) b
Order by yy,mm
Try this one -
Query:
DECLARE #temp TABLE (t VARCHAR(8))
INSERT INTO #temp VALUES
('20120213'),
('20120225'),
('20120218'),
('20120306'),
('20120320')
SELECT LEFT(DATENAME(MONTH, t), 3) + ' ' + y
FROM (
SELECT DISTINCT
t = CAST(LEFT(t, 6) + '01' AS DATETIME)
, y = LEFT(t, 4)
FROM #temp
) t
ORDER BY t
Output:
Feb 2012
Mar 2012
try below query
SELECT
Count (SUBSTRING(CONVERT(char(12), CONVERT(date, StringDate,112),113),4,12)) as counts,
SUBSTRING(CONVERT(char(12), CONVERT(date, StringDate,112),113),4,12) from Employees
group by SUBSTRING(CONVERT(char(12), CONVERT(date, StringDate,112),113),4,12)
output
counts (No column name)
1 Apr 1992
1 Aug 1992
1 Jan 1994
1 Mar 1994
1 May 1992
1 May 1993
1 Nov 1994
2 Oct 1993
Here's a CTE based approach. Replace [[[TABLE_NAME]]] with the actual name of the table that contains the FinalDate field. I did the processing in the final select rather than inside of the CTE to prevent any chance of SQL Server performing the processing on filtered out (non-seq 1) rows.
WITH a AS (
SELECT ROW_NUMBER() OVER (PARTITION BY LEFT(FinalDate, 6) ORDER BY FinalDate) seq, FinalDate
FROM [[[TABLE_NAME]]]
) SELECT LEFT(DATENAME(mm, FinalDate), 3) + ' ' + LEFT(FinalDate, 4)
FROM a
WHERE seq = 1
MSSQL 2008. I am trying to construct a SQL statement which returns the total of column B for all rows where column A is between 2 known ranges. The range is a sliding window, and should be recomputed as it might be using a loop.
Here is an example of what I'm trying to do, much simplified from my actual problem. Suppose I have this data:
table: Test
Year Sales
----------- -----------
2000 200
2001 200
2002 200
2003 200
2004 200
2005 200
2006 200
2007 200
2008 200
2009 200
2010 200
2011 200
2012 200
2013 200
2014 200
2015 200
2016 200
2017 200
2018 200
2019 200
I want to construct a query which returns 1 row for every decade in the above table, like this:
Desired Results:
DecadeEnd TotalSales
--------- ----------
2009 2000
2010 2000
Where the first row is all the sales for the years 2000-2009, the second for years 2010-2019. The DecadeEnd is a sliding window that moves forward by a set ammount for each row in the result set. To illustrate, here is one way I can accomplish this using a loop:
declare #startYear int
set #startYear = (select top(1) [Year] from Test order by [Year] asc)
declare #endYear int
set #endYear = (select top(1) [Year] from Test order by [Year] desc)
select #startYear, #endYear
create table DecadeSummary (DecadeEnd int, TtlSales int)
declare #i int
-- first decade ends 9 years after the first data point
set #i = (#startYear + 9)
while #i <= #endYear
begin
declare #ttlSalesThisDecade int
set #ttlSalesThisDecade = (select SUM(Sales) from Test where(Year <= #i and Year >= (#i-9)))
insert into DecadeSummary values(#i, #ttlSalesThisDecade)
set #i = (#i + 9)
end
select * from DecadeSummary
This returns the data I want:
DecadeEnd TtlSales
----------- -----------
2009 2000
2018 2000
But it is very inefficient. How can I construct such a query?
How about something like
SELECT (Year / 10) * 10,
SUM(Sales)
FROM #Table
GROUP BY (Year / 10) * 10
Have a look at the example here
DECLARE #Table TABLE(
Year INT,
Sales FLOAT
)
INSERT INTO #Table SELECT 2000,200
INSERT INTO #Table SELECT 2001,200
INSERT INTO #Table SELECT 2002,200
INSERT INTO #Table SELECT 2003,200
INSERT INTO #Table SELECT 2004,200
INSERT INTO #Table SELECT 2005,200
INSERT INTO #Table SELECT 2006,200
INSERT INTO #Table SELECT 2007,200
INSERT INTO #Table SELECT 2008,200
INSERT INTO #Table SELECT 2009,200
INSERT INTO #Table SELECT 2010,200
INSERT INTO #Table SELECT 2011,200
INSERT INTO #Table SELECT 2012,200
INSERT INTO #Table SELECT 2013,200
INSERT INTO #Table SELECT 2014,200
INSERT INTO #Table SELECT 2015,200
INSERT INTO #Table SELECT 2016,200
INSERT INTO #Table SELECT 2017,200
INSERT INTO #Table SELECT 2018,200
INSERT INTO #Table SELECT 2019,200
SELECT (Year / 10) * 10,
SUM(Sales)
FROM #Table
GROUP BY (Year / 10) * 10
OUTPUT
Decade SumOfSales
----------- ----------------------
2000 2000
2010 2000
How about:
select sum(sales) as TotalSales, max([year]) as DecadeEnd from Test
group by year / 10
You don't have to do (year / 10) * 10 as long as Year is an integer.
Edit: If year is a float, and the interval is 2.5 years rather than 10
select sum(sales) as TotalSales, max([year]) as DecadeEnd from Test
group by convert(integer, (year * 10)) / 25
IMHO for complex operations you should use .NET method from assembly registered in SQL server.
Since SQL 2005 you can register .NET assembly and call its method from SQL server.
Managed code in SQL
I have a table containing multiple records for different transactions i.e.
ID Date REF
1 01/09/2008 A
1 11/09/2008 A
1 01/10/2008 A
2 01/09/2008 A
2 01/10/2008 A
2 01/11/2008 B
2 01/12/2008 B
and I'm looking to summarise the data so that I have the average days for each id and ref...
i.e.
ID Ref Avg_Days
1 A 15
2 A 30
2 B 30
Thanks in advance if anyone can help
Average day difference is a SUM of differences divided by COUNT(*)
SUM of differences is in fact difference between MIN and MAX:
SELECT id, ref, DATEDIFF(day, MIN(date), MAX(date)) / NULLIF(COUNT(*) - 1, 0)
FROM mytable
GROUP BY
id, ref
Something like this... not really sure how this info will help you with anything though.... need more info as to what your trying to average the days for.
SELECT ID, REF, AVG(DATEPART(day, [Date]))
FROM dbo.Table1
GROUP BY ID, REF
Reference:
AVG,
DATEPART
Using sql server 2005 try this.
DECLARE #Table TABLE(
ID INT,
Date DATETIME,
Ref VARCHAR(MAX)
)
INSERT INTO #Table (ID,Date,Ref) SELECT 1, '01 Sep 2008', 'A'
INSERT INTO #Table (ID,Date,Ref) SELECT 1, '11 Sep 2008', 'A'
INSERT INTO #Table (ID,Date,Ref) SELECT 1, '01 Oct 2008', 'A'
INSERT INTO #Table (ID,Date,Ref) SELECT 2, '01 Sep 2008', 'A'
INSERT INTO #Table (ID,Date,Ref) SELECT 2, '01 Oct 2008', 'A'
INSERT INTO #Table (ID,Date,Ref) SELECT 2, '01 Nov 2008', 'B'
INSERT INTO #Table (ID,Date,Ref) SELECT 2, '01 Dec 2008', 'B'
;WITH Ordered AS (
SELECT ID,
Ref,
Date,
ROW_NUMBER() OVER (PARTITION BY ID, Ref ORDER BY Date) SubNumber
FROM #Table t
)
SELECT Ordered.ID,
Ordered.Ref,
AVG(DATEDIFF(dd, Ordered.Date, OrderedNext.Date)) AVG_Days
FROM Ordered INNER JOIN
Ordered OrderedNext ON Ordered.ID = OrderedNext.ID
AND Ordered.Ref = OrderedNext.Ref
AND Ordered.SubNumber + 1 = OrderedNext.SubNumber
GROUP BY Ordered.ID,
Ordered.Ref
Also have a look at it mathematically:
Let say
([X(1)-X(0)] + [X(2)-X(1)] + [X(3)-X(2)] + ... + [X(n-1)-X(n-2)] + [X(n)-X(n-1)]) / (n-1).
expand the top part as
-X(0) + X(1) - X(1) + X(2) - X(2) + X(3) - ... - X(n-2) + X(n-1) - X(n-1) + X(n)
whcih end up as -X(0) + X(n)
so we have [X(n) - X(0)] / (n - 1)
so take (MAX - MIN) / (Count - 1) for count > 1