How to get week formatted string in sql query - sql

I have the following SQL query (sql server 2008):
SELECT sum(data.freq) as freq,data.week as week FROM (
SELECT
count(daterequested) as freq,
datepart(wk,daterequested) as week,
daterequested
FROM request ma
JOIN contracts mc ON (mc.uid= ma.uid)
JOIN groups og ON og.groupuid = mc.groupuid
JOIN member m ON (m.memberuid = mc.memberuid)
WHERE daterequested BETWEEN
DATEADD(MONTH,-1,GETDATE())
AND
GETDATE()
AND isdeleted = 0
GROUP BY datepart(wk,daterequested),daterequested
--ORDER BY daterequested ASC
) data
GROUP BY data.week
The result is a table with the following data:
Instead of showing the week number I would like to show the week formatted as following:
MM/dd where MM = month and dd is the day where the week starts.
It would be great if I can format starting with first day of the week, then a middle slash, then the last day of that week and finally the month: example: 11-17/04 (April 11 to 17), etc.
Here is the final table that I would like to get:
Any clue?

In case someone needs it just found a solution, maybe is not the best but works.
SELECT sum(data.freq) as freq,
data.week as week, CAST(data.weekstart as varchar) + '-' + CAST(data.weekend as varchar) + '/' + CAST(data.monthend as varchar) as formatweek
FROM (
SELECT
count(daterequested) as freq,
datepart(wk,daterequested) as week,
DATEPART(dd,DATEADD(dd, -(DATEPART(dw, daterequested)-1), daterequested)) weekstart,
DATEPART(dd,DATEADD(dd, 7-(DATEPART(dw, daterequested)), daterequested)) weekend,
DATEPART(mm,DATEADD(dd, 7-(DATEPART(dw, daterequested)), daterequested)) monthend,
daterequested
FROM requestma
JOIN contracts mc ON (mc.uid= ma.uid)
JOIN groups og ON og.groupuid = mc.groupuid
JOIN member m ON (m.memberuid = mc.memberuid)
WHERE daterequested BETWEEN
DATEADD(MONTH,-1,GETDATE())
AND
GETDATE()
AND isdeleted = 0
GROUP BY datepart(wk,daterequested),daterequested
--ORDER BY daterequested ASC
) data
GROUP BY data.week,data.weekstart,data.weekend,data.monthend

Related

Adding a max date subquery to a group by clause

I need to add a max transactional date to this report, so I can see the most recent transaction date for a patient who does not fall under the parameters in the query. This report will be going into a crystal report and I plan to put the last date of service date in the group header for each patient. The code below is to get the max date for each patient. I need the results inserted, so it takes the patients who fall under the below report and gives their max date. Regardless of what is entered for a date. Thank you in advance. SQL Server 2005.
select
patient_id,
Max(proc_chron)
from patient_clin_tran pct
group by patient_id
The Code for the transaction
select patient_id,
(select p.case_status from patient p where p.patient_id = btb.patient_id and p.episode_id = (select max(episode_id) from patient p2 where p2.patient_id = p.patient_id)) as 'Status',
(select p.lname +', '+ p.fname from patient p where p.patient_id = btb.patient_id and p.episode_id = (select max(episode_id) from patient p2 where p2.patient_id = p.patient_id)) AS 'client',
Coverage_plan_id,
(select proc_code from billing_transaction bt where bt.clinical_transaction_no = btb.clinical_transaction_no and bt.coverage_plan_id=btb.coverage_plan_id and bt.coverage_plan_id = btb.coverage_plan_id) as 'Procedure',
proc_chron,
(select billing_amt from billing_transaction bt where bt.clinical_transaction_no = btb.clinical_transaction_no and bt.coverage_plan_id = btb.coverage_plan_id) as 'Billing Amount',
balance_amount,
(select max (accounting_date) from billing_ledger bl where bl.clinical_transaction_no = btb.clinical_transaction_no and subtype = 'pa' and bl.coverage_plan_id = 'standard') as 'Last Payment on Trans',
(select max (instrument_date) from payment p where p.patient_id = btb.patient_id and p.coverage_plan_id = 'standard') as 'Last Payment on Acct',
(select sum(balance_amount) from billing_transaction_balance btb2 where btb2.patient_id=btb.patient_id and btb2.coverage_plan_id=btb.coverage_plan_id and proc_chron <= CONVERT(CHAR(6), DATEADD(year, -1, DATEDIFF(day, 0,GETDATE())), 112) + '01' and btb2.coverage_plan_id in('standard')) AS 'Balance'
from billing_transaction_balance btb
where proc_chron <= CONVERT(CHAR(6), DATEADD(year, -1, DATEDIFF(day, 0, GETDATE())), 112) + '01' and coverage_plan_id in('standard')
group by patient_id, proc_chron, coverage_plan_id, balance_amount, clinical_transaction_no
In your transaction code, you need to add all the Select columns which are not being aggregated to the Group By. I count 8 non-aggregated columns in the Select statement, so you must have all 8 in the Group By.

Select first and last record each day

I have a table with an engineerID, DateTimeCreated as DateTime, JobID and AuditTypeID
I need a query shows first (engineerID, JobID with AuditTypeID 1) and last (engineerID, JobID with AuditTypeID 2) on each row of the query.
SELECT TOP (100) PERCENT
dbo.AuditTrail.EngineerId,
dbo.AuditTrail.AuditTypeId,
dbo.Engineers.Name,
dbo.Engineers.EngineerTypeCode,
dbo.AuditTrail.JobId,
CAST(dbo.AuditTrail.DateTimeCreated AS Date) AS _Date
FROM
dbo.AuditTrail
INNER JOIN
dbo.Engineers
ON dbo.AuditTrail.EngineerId = dbo.Engineers.EngineerId
WHERE
(dbo.AuditTrail.AuditTypeId = 1) AND
(dbo.Engineers.EngineerTypeCode = 'p') AND
(dbo.Engineers.EngineerTypeCode = 'p') AND
(DATEPART(mm, dbo.AuditTrail.DateTimeCreated) = 6) AND
(DATEPART(YYYY, dbo.AuditTrail.DateTimeCreated) = 2014)
group by
AuditTrail.engineerID,
JobID,
AuditTypeId,
Engineers.name,
Engineers.EngineerTypeCode,
CAST(dbo.AuditTrail.DateTimeCreated AS Date)
ORDER BY
dbo.AuditTrail.EngineerID DESC
for the first part of my query. Unfortunatly I cannot see to select the first record for each day
Any help will be greatly appreciated
First just get the data you need, including the create date. Then grouping that data by date, select the min of each day. Finally, join the two sets, selecting only the minimum of each day -- that is, the first occurrence of each day.
with
AllMonth( EngineerId, AuditTypeId, Name, EngineerTypeCode, JobId, DateTimeCreated )as(
SELECT TOP (100) PERCENT
a.EngineerId,
a.AuditTypeId,
e.Name,
e.EngineerTypeCode,
a.JobId,
a.DateTimeCreated
FROM dbo.AuditTrail a
JOIN dbo.Engineers e
ON e.EngineerId = a.EngineerId
AND e.EngineerTypeCode = a.EngineerTypeCode
WHERE
a.AuditTypeId = 1
AND a.EngineerTypeCode = 'p'
AND a.DateTimeCreated >= DateAdd( mm, DateDiff( mm, 0, GetDate()), 0)
AND a.DateTimeCreated < DateAdd( mm, DateDiff( mm, 0, GetDate()) + 1, 0)
),
FirstByDay( MinDate )as(
select Min( DateTimeCreated )
from AllMonth
group by cast( DateTimeCreated AS Date )
)
select *
from AllMonth a
join FirstByDay f
on f.MinDate = a.DateTimeCreated
ORDER BY a.EngineerID DESC;
To get the last item of each day, just add a max to FirstByDay and add to the join. Work it into one long row if you really want to.
Btw, didn't I hear a few years back that the later versions of MSSQL ignored top (100) percent? I don't work with it much these days, and my memory is...well, just...somewhere around here...

Normalization of Year bringing nulls back

I have the following query:
SELECT DISTINCT
YEAR(DateRegistered) as Years,
Months.[MonthName],
COUNT(UserID)as totalReg
FROM
Months WITH(NOLOCK)
LEFT OUTER JOIN
UserProfile WITH(NOLOCK)
ON
Months.MonthID = MONTH(DateRegistered)
AND
DateRegistered > DATEADD(MONTH, -12,GETDATE())
GROUP BY YEAR(DateRegistered), Months.[MonthName]
ORDER BY Months.[MonthName]
As you can tell this will always bring back 12 months worth of data. As such it is working, although there is a bug with this method.
It creates Null values in months where there is no data, now the record should exist(whole point of the query) but Year field is bringing Nulls which is something I dont want.
Now I understand the problem is because there is no data, how is it supposed to know what year?
So my question is - is there any way to sort this out and replace the nulls? I suspect I will have to completely change my methodology.
**YEAR** **MONTH** **TOTAL**
2013 April 1
2013 August 1
NULL December 0
2013 February 8
2013 January 1
2013 July 1
NULL June 0
2013 March 4
NULL May 0
NULL November 0
NULL October 0
2012 September 3
If you want 12 months of data, then construct a list of numbers from 1 to 12 and use these as offsets with getdate():
with nums as (
select 12 as level union all
select level - 1
from nums
where level > 1
)
select YEAR(thedate) as Years,
Months.[MonthName],
COUNT(UserID) as totalReg
FROM (select DATEADD(MONTH, - nums.level, GETDATE()) as thedate
from nums
) mon12 left outer join
Months WITH (NOLOCK)
on month(mon12.thedate) = months.monthid left outer join
UserProfile WITH (NOLOCK)
ON Months.MonthID = MONTH(DateRegistered) and
DateRegistered > DATEADD(MONTH, -12, GETDATE())
GROUP BY YEAR(thedate), Months.[MonthName]
ORDER BY Months.[MonthName];
I find something strange about the query though. You are defining the span from the current date. However, you seem to be splitting the months themselves on calendar boundaries. I also find the table months to be awkward. Why aren't you just using the datename() and month() functions?
Try this out:
;With dates as (
Select DateName(Month, getdate()) as [Month],
DatePart(Year, getdate()) as [Year],
1 as Iteration
Union All
Select DateName(Month,DATEADD(MONTH, -Iteration, getdate())),
DatePart(Year,DATEADD(MONTH, -Iteration, getdate())),
Iteration + 1
from dates
where Iteration < 12
)
SELECT DISTINCT
d.Year,
d.Month as [MonthName],
COUNT(up.UserID)as totalReg
FROM dates d
LEFT OUTER JOIN UserProfile up ON d.Month = DateName(DateRegistered)
And d.Year = DatePart(Year, DateRegistered)
GROUP BY d.Year, d.Month
ORDER BY d.Year, d.Month
Here's my attempt at a solution:
declare #UserProfile table
(
id bigint not null identity(1,1) primary key clustered
, name nvarchar(32) not null
, dateRegistered datetime not null default(getutcdate())
)
insert #UserProfile
select 'person 1', '2011-01-23'
union select 'person 2', '2013-01-01'
union select 'person 3', '2013-05-27'
declare #yearMin int, #yearMax int
select #yearMin = year(MIN(dateRegistered))
, #yearMax= year(MAX(dateRegistered))
from #UserProfile
;with monthCte as
(
select 1 monthNo, DATENAME(month, '1900-01-01') Name
union all
select monthNo + 1, DATENAME(month, dateadd(month,monthNo,'1900-01-01'))
from monthCte
where monthNo < 12
)
, yearCte as
(
select #yearMin yearNo
union all
select yearNo + 1
from yearCte
where yearNo < #yearMax
)
select y.yearNo, m.Name, COUNT(up.id) UsersRegisteredThisPeriod
from yearCte y
cross join monthCte m
left outer join #UserProfile up
on year(up.dateRegistered) = y.yearNo
and month(up.dateRegistered) = m.monthNo
group by y.yearNo, m.monthNo, m.Name
order by y.yearNo, m.monthNo
SQL Fiddle Version: http://sqlfiddle.com/#!6/d41d8/6640
You have to calculate the counts in a Derived Table (or a CTE) first and then join
untested:
SELECT
COALESCE(dt.Years, YEAR(DATEADD(MONTH, -Months.MonthID, GETDATE()))),
Months.[MonthName],
COALESCE(dt.totalReg, 0)
FROM
Months WITH(NOLOCK)
LEFT OUTER JOIN
(
SELECT
YEAR(DateRegistered) AS Years,
MONTH(DateRegistered) AS Mon,
COUNT(UserID)AS totalReg
FROM UserProfile WITH(NOLOCK)
WHERE DateRegistered > DATEADD(MONTH, -12,GETDATE())
GROUP BY
YEAR(DateRegistered),
MONTH(DateRegistered)
) AS dt
ON Months.MonthID = dt.mon
ORDER BY 1, Months.MonthID
I changed the order to Months.MonthID instead of MonthName and i added year because you might have august 2012 and 2013 in your result.

I need help displaying a field that is zero

In this query I'm counting work orders that were created the previous week and displaying a count by wotype2. If a wotype2 for the previous week is zero, I need the wotype2 to appear in my results. Any ideas on how to pull this off?
-- Retrieve Last Week's New Work Orders.
DECLARE #TodayDayOfWeek INT
DECLARE #EndOfPrevWeek DateTime
DECLARE #StartOfPrevWeek DateTime
--get number of a current day (1-Monday, 2-Tuesday... 7-Sunday)
SET #TodayDayOfWeek = datepart(dw, GetDate())
--get the last day of the previous week (last Sunday)
SET #EndOfPrevWeek = DATEADD(dd, -#TodayDayOfWeek, GetDate())
--get the first day of the previous week (the Monday before last)
SET #StartOfPrevWeek = DATEADD(dd, -(#TodayDayOfWeek+6), GetDate())
SELECT wotype2 as WOType, COUNT(*) as NewWOsLastWeek
FROM tasks
WHERE ((OpenDATE BETWEEN
CONVERT(VARCHAR, #StartOfPrevWeek,7) AND
CONVERT(VARCHAR, #EndOfPrevWeek+1,7)) AND
(TYPE = 'Information Systems') AND
(RESPONS != 'ADMIN'))
group by wotype2
order by wotype2
You may need to do an outer join (say a left outer join) with a table which has all the possible values of wotype2.
If there is such a table, let's say it's named wotype2s, then the SQL would be:
SELECT wotype2s.wotype2 as WOType, COUNT(*) as NewWOsLastWeek
FROM wotype2s left outer join tasks on wotype2s.wotype2 = tasks.wotype2
WHERE ((OpenDATE BETWEEN
CONVERT(VARCHAR, #StartOfPrevWeek,7) AND
CONVERT(VARCHAR, #EndOfPrevWeek+1,7)) AND
(TYPE = 'Information Systems') AND
(RESPONS != 'ADMIN'))
group by wotype2s.wotype2
order by wotype2s.wotype2
or, if there is no such table,
SELECT wotype2s.wotype2 as WOType, COUNT(*) as NewWOsLastWeek
FROM (select distinct wotype2 from tasks) wotype2s
left outer join tasks on wotype2s.wotype2 = tasks.wotype2
WHERE ((OpenDATE BETWEEN
CONVERT(VARCHAR, #StartOfPrevWeek,7) AND
CONVERT(VARCHAR, #EndOfPrevWeek+1,7)) AND
(TYPE = 'Information Systems') AND
(RESPONS != 'ADMIN'))
group by wotype2s.wotype2
order by wotype2s.wotype2

Calculating number of days between Admission Date and today

I found the following in Stackoverflow and have been working with it to find the number of Patient Days each month. It works very well if I have both the Admit and Discharge dates.
I can't figure out how to edit it to calculate the Patient days when the discharge date has not been completed... the patient is still in the hospital. If feels like I should use Coalesce or ISNULL to find the records where the Discharge Date is NULL, but I'm not a programmer and would appreciate your help.
WITH Mos AS (
SELECT
D.ED_ADMIT_DATE,
D.ED_DISCHARGE_DATE,
Number,
DateAdd(Month, Number, D.ED_ADMIT_DATE - Day(D.ED_ADMIT_DATE) + 1) MoDate
FROM
cases_cstm D
INNER JOIN master.dbo.spt_values V ON V.Number <= DateDiff(Month, D.ED_ADMIT_DATE, D.ED_DISCHARGE_DATE)
WHERE
V.Type = 'P'), Dys AS (
SELECT
MoDate,
DateDiff(
Day,
CASE WHEN Number = 0 THEN ED_ADMIT_DATE ELSE MoDate END,
CASE WHEN Number = DateDiff(Month, ED_ADMIT_DATE, ED_DISCHARGE_DATE) THEN ED_DISCHARGE_DATE ELSE DateAdd(Month, 1, MoDate) -1
END
) + 1 Cnt
FROM Mos)
SELECT Year(MoDate) Yr,
Coalesce(DateName(Month, MoDate), 'Total') Mo,
Convert(varchar(11), Sum(Cnt)) + ' day' + CASE WHEN Sum(Cnt) = 1 THEN '' ELSE 's' END Descr
FROM Dys
GROUP BY MoDate
WITH ROLLUP
ORDER BY
Grouping(MoDate),
MoDate;
You could replace each occurance of ED_DISCHARGE_DATE with:
IsNull(ED_DISCHARGE_DATE,getdate())
This uses the current time whenever the discharge date is unavailable.