I am using Microsoft SQL Server Management Studio and I am trying to do the following: I want to make a calculation that looks for the last 2 months and the "current" month.
The month and year are defined as follows:
SELECT
ID,
dc.Year * 100 + dc.MonthOfYear AS YYYMM,
dc.Year * 100 + dc.MonthOfYear - 1 AS PrevMonth,
COUNT(1) AS Count_sales,
SUM(sales) AS TotalSales
FROM
xx (NOLOCK) dc
GROUP BY
dc.Year * 100 + dc.[Month Of Year]
The problem occurs when I have 202101 because the previous month is taken as 202102 any know how to handle when the year changes as well please?
I have tried to using the following but in SQL Server, the add_months function doesn't exists:
Hive SQL Integer YYYYMM previous Months
Any suggestions please?
It will not be the prettiest of code but you can use case here:
select
ID
,dc.Year*100+dc.MonthOfYear as YYYMM
,case when dc.MonthOfYear = 1 then dc.Year-1 else dc.Year end * 100 + dc.MonthOfYear - (case when dc.MonthOfYear = 1 then -11 else 1 end) as PrevMonth
,dc.MonthOfYear-case when dc.MonthOfYear = 1 then -11 else 1 end as PrevMonthXX
,count(1) as Count_sales
,sum(sales) as TotalSales
from xx (nolock) dc
group by dc.Year*100+dc.[Month Of Year]
It is most often easier to save as a regular date and then just take out year and month if you need it seperatly later on. But sometimes you just have do make do with what you have..
Related
I need all the rows that are 14 days next to my current date and that should not depend upon the Year. For example if today is 2nd of September, then the query should return all the rows of which u_dateofmanufacture is (2+14) 16th September, no matter which year it belongs. the focus is only on the date and the month.
I have also attached the screenshot and the column "date of Manufacture" is highlighted.
According to the screenshot only the rows 2,3 and 4 should be returned. They all have different year but the day and month is same(09-16).
I am using SQL Server.
declare #date DATE = dateadd(d,14,getdate())
select * from your table where month(u_dateofmanufacture)= month(#date) and day(u_dateofmanufacture) = day(#date)
You have a problem with leap years and the first 14 days of the year. If we skip these problems, you can use:
where month(datecol + 14) * 100 + day(datecol + 14) >= month(getdate()) * 100 + day(getdate()) and
month(datecol) * 100 + day(datecol) < month(getdate()) * 100 + day(getdate())
I would use a join on a virtual table containing all the possible years
SELECT t.*
FROM YourTable t
JOIN (
SELECT
starting = DATEADD(day, -14, DATEFROMPARTS(v.year, MONTH(GETDATE(), DAY(GETDATE())),
ending = DATEFROMPARTS(v.year, MONTH(GETDATE(), DAY(GETDATE()))
FROM (VALUES
(2023),(2022),(2022),(2021),(2020),(2019),(2018),(2017),(2016),(2015),(2014),(2013),(2012),(2011)
) v(year)
) v ON t.u_dateofmanufacture >= v.starting
AND t.u_dateofmanufacture < v.ending
you can use a query like below
select * from yourtable
where month(u_dateofmanufacture)= month(dateadd(d,14,getdate()))
and day(u_dateofmanufacture) =day(dateadd(d,14,getdate()))
optimally
declare #seekdate = dateadd(d,14,getdate())
select * from yourtable
where month(u_dateofmanufacture)= month(#seekdate )
and day(u_dateofmanufacture) =day(#seekdate)
I am writing a course project (something like a program for the hotel manager) and I need a little help. I have tables Reservations and Rooms and I need to calculate the amount of payment after the client leaves the room ((End_date - Start_date) * price_per_day), but I'm having trouble getting the price_per_day from the table Rooms.
My query only works if there is one record in the Resertvation table, if there are 2 or more, I get an error "subquery returned more than 1 value" and I don’t know how to fix it (the problem is in this part of the query SELECT price_per_day FROM Rooms AS ro JOIN Reservations AS re ON ro.room_id = re.room_id)
I'm using visual studio 2019 + SQL Server Express LocalDB.
I will be grateful for any help or hint!
UPDATE Reservations
SET Amount_payable = (
DATEDIFF(day, CONVERT(datetime, Start_date, 104), CONVERT(datetime, End_date, 104) * (SELECT price_per_day FROM Rooms AS ro JOIN Reservations AS re ON ro.room_id = re.room_id))
)
WHERE Status = 'Archived'
Table Reservations
reservation_id customer_id room_id start_date end_date status Amount_payable
1 3 3 12.04.2020 05.06.2020 Archived 0
2 2 4 11.04.2020 30.05.2020 Active 0
Table Rooms
reservation_id room_id number_of_persons room_type price_per_day
0 1 3 Double 300
0 2 4 Triple 600
0 3 3 Studio 400
2 4 2 Single 444
you need slightly different approach to resolve the issue.
try the following:
UPDATE re
SET
Amount_payable = (DATEDIFF(day, CONVERT(DATETIME, Start_date, 104), CONVERT(DATETIME, End_date, 104)) * price_per_day)
FROM Reservations re
JOIN Rooms AS ro ON ro.room_id = re.room_id
WHERE STATUS = 'Archived';
I'm trying to group by according to month from datetime
I run below query
select cf.flow_name as 'Process', COUNT(c.case_ID) as 'Case', CONVERT(VARCHAR(10),c.xdate,104) as 'Date'
from cases c inner join case_flow cf on c.case_flow_ID=cf.CF_ID
where project_ID=1 and c.subject_ID=1
group by cf.flow_name,c.xdate
Columns data types as below
flow_name varchar(100)
case_ID int
xdate datetime
Result displays like below if i run above query
Process - Case - Date
Test 1 30.01.2015
Test 1 30.01.2015
analysis 1 19.03.2015
analysis 1 30.03.2015
analysis 1 13.04.2015
analysis 1 16.04.2015
Question:
I need to group by as below (group by according to month for x.date)
Correct Result should be as below
Process - Case - Date
Test 2 30.01.2015 (Because Test has 2 data from 01 month)
analysis 2 19.03.2015 (Because analysis has 2 data from 03 month)
analysis 2 13.04.2015 (Because analysis has 2 data from 04 month)
as above all result should group by month how can i do this according to my query ?
hope you understand my english thanks
SELECT cf_flow,
Count(*),
Min(xdate)
FROM cases c
INNER JOIN case_flow cf
ON c.case_flow_id = cf.cf_id
WHERE project_id = 1
AND c.subject_id = 1
GROUP BY cf_flow,
Dateadd(month, Datediff(month, 0, xdate), 0)
Sample data in tblData:
RowID SID Staken DateTaken
---------------------------------------------
1 1 1 2014-09-15 14:18:11.997
2 1 1 2014-09-16 14:18:11.997
3 1 1 2014-09-17 14:18:11.997
I would like to get the daywise count of SIDs and also a cumulative sum like
Date ThisDayCount TotalCount
-----------------------------------
2014-09-15 1 1
2014-09-16 10 11
2014-09-17 30 41
This is what I have now in my stored procedure with the start & end date parameters. Is there a more elegant way to do this?
;WITH TBL AS
(
SELECT
CONVERT(date, asu.DateTaken) AS Date,
COUNT(*) AS 'ThisDayCount'
FROM
tblData asu
WHERE
asu.SID = 1
AND asu.STaken = 1
AND asu.DateTaken >= #StartDate
AND asu.DateTaken <= #EndDate
GROUP BY
CONVERT(date, asu.DateTaken)
)
SELECT
t1.Date, t1.ThisDayCount, SUM(t1.ThisDayCount) AS 'TotalCount'
FROM
TBL t1
INNER JOIN
TBL t2 ON t1.date >= t2.date
GROUP BY
t1.Date, t1.ThisDayCount
I am not aware of a more elegant way to do that, other than perhaps with a subquery for your running total. What you have is pretty elegant by T-SQL standards.
But, depending on how many records you have to process and what your indexes look like, this could be very slow. You don't say what the destination of this information is, but if it's any kind of report or web page, I'd consider doing the running total as part of the processing at the destination rather than in the database.
I am creating a query to give number of days between two days based on year. Actually I have below type of date range
From Date: TO_DATE('01-Jun-2011','dd-MM-yyyy')
To Date: TO_DATE('31-Dec-2013','dd-MM-yyyy')
My Result should be:
Year Number of day
------------------------------
2011 XXX
2012 XXX
2013 XXX
I've tried below query
WITH all_dates AS
(SELECT start_date + LEVEL - 1 AS a_date
FROM
(SELECT TO_DATE ('21/03/2011', 'DD/MM/YYYY') AS start_date ,
TO_DATE ('25/06/2013', 'DD/MM/YYYY') AS end_date
FROM dual
)
CONNECT BY LEVEL <= end_date + 1 - start_date
)
SELECT TO_CHAR ( TRUNC (a_date, 'YEAR') , 'YYYY' ) AS YEAR,
COUNT (*) AS num_days
FROM all_dates
WHERE a_date - TRUNC (a_date, 'IW') < 7
GROUP BY TRUNC (a_date, 'YEAR')
ORDER BY TRUNC (a_date, 'YEAR') ;
I got exact output
Year Number of day
------------------------------
2011 286
2012 366
2013 176
My question is if i use connect by then query execution takes long time as i have millions of records in table and hence i don't want to use connect by clause
connect by clause is creating virtual rows against the particular record.
Any help or suggestion would be greatly appreciated.
From your vague expected results I think you want the number of records between those dates, not the number of days; but it's rather unclear. Since you refer to a table in the question I assume you want something related to the table data, not simply days between two dates which wouldn't depend on a table at all. (I have no idea what the connect by clause reference means though). This should give you that, if it is what you want:
select extract(year from date_field), count(*)
from t42
where date_field >= to_date('01-Jun-2011', 'DD-MON-YYYY')
and date_field < to_date('31-Dec-2013') + interval '1' day
group by extract(year from date_field)
order by extract(year from date_field);
The where clause is as you'd expect between two dates; I've assumed there might be times in your date field (i.e. not all at midnight) and that you want to count all records on the last date in your range. Then it's grouping and counting based on the year for each record.
SQL Fiddle.
If you want the number of days that have records within the range, then you can just vary the count slightly:
select extract(year from date_field), count(distinct trunc(date_field))
...
SQL Fiddle.
you can use the below function to reduce the number of virtual rows by considering only the years in between.You can check the SQLFIDDLE to check the performance.
First consider only the number of days between start date and the year end of that year or
End date if it is in same year
Then consider the years in between from next year of start date to the year before the end date year
Finally consider the number of days from start of end date year to end date
Hence instead of iterating for all the days between start date and end date we need to iterate only the years
WITH all_dates AS
(SELECT (TO_CHAR(START_DATE,'yyyy') + LEVEL - 1) YEARS_BETWEEN,start_date,end_date
FROM
(SELECT TO_DATE ('21/03/2011', 'DD/MM/YYYY') AS start_date ,
TO_DATE ('25/06/2013', 'DD/MM/YYYY') AS end_date
FROM dual
)
CONNECT BY LEVEL <= (TO_CHAR(end_date,'yyyy')) - (TO_CHAR(start_date,'yyyy')-1)
)
SELECT DECODE(TO_CHAR(END_DATE,'yyyy'),YEARS_BETWEEN,END_DATE
,to_date('31-12-'||years_between,'dd-mm-yyyy'))
- DECODE(TO_CHAR(START_DATE,'yyyy'),YEARS_BETWEEN,START_DATE
,to_date('01-01-'||years_between,'dd-mm-yyyy'))+1,years_between
FROM ALL_DATES;
In Oracle you can perform Addition and Substraction to dates like this...
SELECT
TO_DATE('31-Dec-2013','dd-MM-yyyy') - TO_DATE('01-Jun-2011','dd-MM-yyyy')
DAYS FROM DUAL;
it will return day difference between two dates....
select to_date(2011, 'yyyy'), to_date(2012, 'yyyy'), to_date(2013, 'yyyy')
from dual;
TO_DATE(2011,'Y TO_DATE(2012,'Y TO_DATE(2013,'Y
--------------- --------------- ---------------
01-MAY-11 01-MAY-12 01-MAY-13
select to_char(date_field,'yyyy'), count(*)
from your_table
where date_field between to_date('01-Jun-2011', 'DD-MON-YYYY')
and to_date('31-Dec-2013 23:59:59', 'DD-MON-YYYY hh24:mi:ss')
group by to_char(date_field,'yyyy')
order by to_char(date_field,'yyyy');