Building Subquery to be a column/Field Name - sql

I am unable to bundled groups of subqueries correctly in order to create column titled "Discharge_To"
I am using Teradata Studio Express. I was asked to create a column for field that is not inside a table we normally used. We want to know where a patient was discharged to from a previous place of service. In order to answer this, there has to be steps to determine that. So far, I can get it read correctly until line 94.
Select S.Member_ID, S.PAC_Sty_ID, S.Stay_Admit_Date, S.Stay_Discharge_Date, S.POS, S.LOS,
(
Select
S.Member_ID, S.PAC_Sty_ID,
Case
When S.Discharge_To is null
and H.POS is not null And S.POS <> '12' then 'Home With Care'
When S.Discharge_To is null then 'Home Without Care'
Else S.Discharge_To
End Discharge_To
From (
Select
S.Member_ID, S.PAC_Sty_ID, S.Stay_Admit_Date, S.Stay_Discharge_Date, S.POS,
Case trim(D.POS)
When '21' then 'Hospital' When '23' then 'ER' When '31' then 'SNF'
When '61' then 'IRF' When 'LTAC' then 'LTAC'
End Discharge_To
From ECONIMICS.PAC_02_MODEL_SUMMARY_Combined S
Left Join (
Select S.Member_ID, S.PAC_Sty_ID, S.POS, S.Stay_Admit_Date, S.Stay_Discharge_Date
From ECONIMICS.PAC_02_MODEL_SUMMARY_Combined S
Where PAC_Sty_ID is not null
And POS <> '12'
) D On D.Member_ID = S.Member_ID And D.PAC_Sty_ID <> S.PAC_Sty_ID
And D.Stay_Admit_Date Between S.Stay_Admit_Date and S.Stay_Discharge_Date + 1
Where S.PAC_Sty_ID is not null
Qualify Row_Number() Over (
Partition By S.PAC_Sty_ID Order By Case trim(D.POS)
When '21' then 1 When 'LTAC' then 2 when '61' then 3 When '31' then 4 end
) = 1
) S
Left Join (
Select *
From ECONIMICS.PAC_02_MODEL_SUMMARY_Combined
Where POS = '12'
) H On H.Member_ID = S.Member_ID
And H.From_Date Between S.Stay_Discharge_Date and S.Stay_Discharge_Date + 7
Qualify Row_Number() Over (Partition By S.PAC_Sty_ID Order By H.From_Date) = 1
) E On E.Member_ID = S.Member_ID And E.PAC_Sty_ID = S.PAC_Sty_ID
Where S.PAC_Sty_ID is not Null
AND S.STAY_DISCHARGE_DATE between '2017-01-01' and '2020-12-31'
AND S.LOB in ('CARE', 'DUAL')
AND S.ORPHAN_CLM_ID IS NULL
AND S.ORPHAN_CLM_LN IS NULL
Group By 1, 2, 3, 4, 5, 6
There should be 7 columns with the 7th column titled "Discharge_to" and values in the seventh column would be text (e.g., "Home without Care")

Posting here, since it's easier. Your query doesn't seem to be formatted correctly. It's of this form:
select S.Member_ID, ... ,
(
Select ... -- Sub-query trying to derive Discharge_To field
) E on E.Member_ID = S.Member_ID ...
where ...
A couple notes:
There is no FROM clause in the outer query yet you are trying to return S. fields
There is no S result set to join your E result to
The E result set is trying to be used as a sub-SELECT, but it also has an alias
Not knowing what your error message is, I'd suggest breaking apart the query into its sub-queries and running those individually to try to determine where the problem lies.

Related

SQL - Adding conditions to SELECT

I have a table which has a timestamp and inCycle status of a machine. I'm using two CTE's and doing an INNER JOIN on row number so I can easily compare the timestamp of one row to the next. I have the DATEDIFF working and now I need to look at the inCycle status. Basically, if the inCycleThis and inCycleNext both = 1, I need to add it to an InCycle total.
Similarly (Shown table will make this clear):
incycleThis/next = 0,1 = not in cycle
incycleThis/next = 0,0 = not in cycle
incycleThis/next = 1,1 = in cycle
If I was doing this client side, this would be pretty simple. I need to do this in a stored procedure though due to there being a lot of records. I'd love to use an 'IF' in the SELECT section, but it seems that's not how it works.
The result I'm looking for at the end is simply: InCycle = Xtime. Something like:
SUM(Diff_seconds if((InCycleThis = 1 AND InCycleNext = 1) OR (InCycleThis = 1 AND InCycleNext = 0))
This is what I have so far:
WITH History_CTE (DT, MID, FRO, IC, RowNum)
AS
(
SELECT DateAndTime
,MachineID
,FeedRateOverride
,InCycle
,ROW_NUMBER()OVER(ORDER BY MachineID, DateAndTime) AS "row number"
FROM History
WHERE DateAndTime >= '2020-11-15'
AND DateAndTime < '2020-11-16'
),
History2_CTE (DT2, MID2, FRO2, IC2, RowNum2)
AS
(
SELECT DateAndTime
,MachineID
,FeedRateOverride
,InCycle
,ROW_NUMBER()OVER(ORDER BY MachineID, DateAndTime) AS "row number"
FROM History
WHERE DateAndTime >= '2020-11-15'
AND DateAndTime < '2020-11-16'
)
SELECT DT as 'TimeStamp'
,DT2 as 'TimeStamp Next Row'
,MID
,FRO
,IC as 'InCycle this'
,IC2 as 'InCycle next'
,RowNum
,DATEDIFF(s, History2_CTE.DT2, History_CTE.DT) AS 'Diff_seconds'
FROM History_CTE
INNER JOIN
History2_CTE ON History_CTE.RowNum = History2_CTE.RowNum2 + 1
Consider adding a third CTE to first conditionally calculate your needed value. Then aggregate for final statement. Recall CTEs can reference previously defined CTEs. Be sure to always quailfy columns with table aliases in JOIN queries.
WITH
... first two ctes...
, sub AS (
SELECT h1.DT AS 'TimeStamp'
, h2.DT2 AS 'TimeStamp Next Row'
, h1.MID
, h1.FRO
, h1.IC AS 'InCycle this'
, h2.IC2 AS 'InCycle next'
, h1.RowNum
, DATEDIFF(s, h2.DT2, h1.DT) AS 'Diff_seconds'
, CASE
WHEN (h1.IC = 1 AND h2.IC2 = 1) OR (h1.IC= 1 AND h2.IC2 = 0)
THEN DATEDIFF(s, h2.DT2, h1.DT)
END AS 'IC_Diff_seconds'
FROM History_CTE h1
INNER JOIN History2_CTE h2
ON h1.RowNum = h2.RowNum2 + 1
)
SELECT SUM([Diff_seconds]) AS Diff_seconds_Total
, SUM([IC_Diff_seconds]) AS IC_Diff_seconds_Total
FROM sub
And if needing to add groupings, incorporate GROUP BY:
SELECT h1.MID
, h1.FRO
, SUM([Diff_seconds]) AS Diff_seconds_Total
, SUM([IC_Diff_seconds]) AS IC_Diff_seconds_Total
FROM sub
GROUP BY h1.MID
, h1.FRO
Even aggregate calculations by day:
SELECT CONVERT(date, [TimeStamp]) AS [Day]
, SUM([Diff_seconds]) AS Diff_seconds_Total
, SUM([IC_Diff_seconds]) AS IC_Diff_seconds_Total
FROM sub
GROUP BY CONVERT(date, [TimeStamp])
The result I'm looking for at the end is simply: InCycle = Xtime. Something like:
SUM(Diff_seconds if((InCycleThis = 1 AND InCycleNext = 1) OR (InCycleThis = 1 AND InCycleNext = 0))
As I understand your question, you just need to sum the difference betwen the timestamp of "in cycle" rows and the timestamp of the next row.
select machineid,
sum(datediff(s, dateandtime, lead_dateandtime)) as total_in_time
from (
select h.*,
lead(dateandtime) over(partition by machineid order by dateandtime) as lead_dateandtime
from history h
) h
where inclycle = 1
group by machineid

How to select data without using group?

My base data based on dealer code only but in one condition we need to select other field as well to matching the condition in other temp table how can i retrieve data only based on dealercode ith matching the condition on chassis no.
Below is the sample data:
This is how we have selected the data for the requirement:
---------------lastyrRenewalpolicy------------------
IF OBJECT_ID('TEMPDB..#LASTYRETEN') IS NOT NULL DROP TABLE #LASTYRETEN
select DEALERMASTERCODE , count(*) RENEWALEXPRPOLICY,SUM(NETOD_YEAR_PREM_PART_A) AS 'ACHIEVED-ODPREMIUM_RENEWAL' into #LASTYRETEN
from [dbo].[T_RE_POLICY_TRANSACTION]
where cast (InsPolicyCreatedDate as date) between #FirstDayC and #LastDayC
AND PolicyStatus= 'Renewal' AND (ltrim(rtrim(ISCANCELLEDSTATUS)) = 0 ) group by DEALERMASTERCODE
-----------------lastrollower------------------------
IF OBJECT_ID('TEMPDB..#LASTYROLWR') IS NOT NULL DROP TABLE #LASTYROLWR
select DEALERMASTERCODE , count(*) ROLLOWEEXPRPOLICY ,SUM(NETOD_YEAR_PREM_PART_A) AS 'ACHIEVED-ODPREMIUM_ROLLOVER'
into #LASTYROLWR from [dbo].[T_RE_POLICY_TRANSACTION] where cast (InsPolicyCreatedDate as date) between #FirstDayC and #LastDayC
AND PolicyStatus= 'ROLLOVER' AND (ltrim(rtrim(ISCANCELLEDSTATUS)) = 0 ) group by DEALERMASTERCODE
And continue with above flow Below is the other select statement which creating issue at the end due to grouping
:
-------------OTHERYRBASE(EXPIRYRENEWAL)--------------
IF OBJECT_ID('TEMPDB..#OTHERYRBASEEXPIRY') IS NOT NULL DROP TABLE #OTHERYRBASEEXPIRY
select DEALERMASTERCODE ,ChassisNo , count(*) RENEWALPOLICYEXPIRY
into #OTHERYRBASEEXPIRY
from [dbo].[T_RE_POLICY_TRANSACTION] where cast (PolicyExpiryDate as date) between '2020-08-01' and '2020-08-31'
and BASIC_PREM_TOTAL <> 0 AND PolicyStatus in ('Renewal','rollover') and BusinessType='jcb'
AND (ltrim(rtrim(ISCANCELLEDSTATUS)) = 0 ) group by DEALERMASTERCODE,ChassisNo
-------------OTHERYRBASE(EXPIRYRENEWAL)--------------
IF OBJECT_ID('TEMPDB..#OTHERYRCON') IS NOT NULL DROP TABLE #OTHERYRCON
select OTE.DEALERMASTERCODE ,OTE.ChassisNo , count(*) OTHERYRCON into #OTHERYRCON
from [dbo].[T_RE_POLICY_TRANSACTION] OTE INNER JOIN #OTHERYRBASEEXPIRY EXP
ON OTE.ChassisNo=EXP.ChassisNo
where cast(CREATED_DATE as date) between '2020-06-01' and '2020-12-31' and BusinessType='jcb'
and OTE.BASIC_PREM_TOTAL <> 0 AND OTE.PolicyStatus = 'Renewal'
AND (ltrim(rtrim(ISCANCELLEDSTATUS)) = 0 ) group by OTE.DEALERMASTERCODE,OTE.ChassisNo
Thanks a lot in advance for helping and giving a solution very quickly ///
After taking a look at this code it seems possible there was an omitted JOIN condition in the last SELECT statement. In the code provided the JOIN condition is only on ChassisNo. The GROUP BY in the prior queries which populates the temporary table also included the DEALERMASTERCODE column. I'm thinking DEALERMASTERCODE should be added to the JOIN condition. Something like this
select OTE.DEALERMASTERCODE ,OTE.ChassisNo , count(*) OTHERYRCON
into #OTHERYRCON
from [dbo].[T_RE_POLICY_TRANSACTION] OTE
INNER JOIN #OTHERYRBASEEXPIRY EXP ON OTE.DEALERMASTERCODE=EXP.DEALERMASTERCODE
and OTE.ChassisNo=EXP.ChassisNo
where cast(CREATED_DATE as date) between '2020-06-01' and '2020-12-31'
and BusinessType='jcb'
and OTE.BASIC_PREM_TOTAL <> 0
AND OTE.PolicyStatus = 'Renewal'
AND (ltrim(rtrim(ISCANCELLEDSTATUS)) = 0 )
group by OTE.DEALERMASTERCODE,OTE.ChassisNo;

OPTIMIZING QUERY - ORACLE SQL

I have a query fetching information from a large database. Fetching one customer records takes minimum 12 seconds. I have estimated doing through the whole table will require not less than 12 days. Have a look at a it and help if it can be optimized
SELECT gam.CIF_ID
, TO_CHAR(T1.TRAN_DATE, 'MM') AS MONTH
, SUM(TBAADM.COMMONPACKAGE.getConvertedAmount('TZ', tran_amt, tran_crncy_code, 'TZS', 'REV', tran_date)) AS TOTAL_DEBIT_AMT
, ROUND(AVG(TBAADM.COMMONPACKAGE.getConvertedAmount('TZ', tran_amt, tran_crncy_code, 'TZS', 'REV', tran_date)), 3) AS AVG_DEBIT_AMT
, COUNT(T1.PART_TRAN_TYPE) AS NUMBER_OF_DEBIT_TRANSACTIONS
FROM TBAADM.HIST_TRAN_DTL_TABLE T1
LEFT JOIN TBAADM.GENERAL_ACCT_MAST_TABLE gam ON ( gam.ACID = T1.ACID )
WHERE T1.PART_TRAN_TYPE = 'D'
AND NOT EXISTS (
SELECT 1
FROM TBAADM.HIST_TRAN_DTL_TABLE T3
INNER JOIN TBAADM.GENERAL_ACCT_MAST_TABLE g ON ( g.ACID = T3.ACID )
WHERE T3.PART_TRAN_TYPE ='C'
AND T3.TRAN_DATE || T3.TRAN_ID=T1.TRAN_DATE || T1.TRAN_ID
AND g.cif_id = gam.cif_id
)
AND (
T1.TRAN_SUB_TYPE='CI'
OR T1.TRAN_SUB_TYPE='SI'
OR T1.TRAN_SUB_TYPE='PI'
OR T1.TRAN_SUB_TYPE='RI'
)
AND gam.ACCT_OWNERSHIP <> 'O'
AND T1.TRAN_SUB_TYPE <> 'CP'
AND gam.SCHM_TYPE <> 'LAA'
AND tran_particular LIKE 'POS PURCHASE %'
AND T1.TRAN_DATE BETWEEN '1/JAN/14' AND '30/JUNE/18'
GROUP BY TO_CHAR(T1.TRAN_DATE, 'MM')
, gam.CIF_ID
;

Month Aggregation with 0 for NULL results

I have seen something similar but I can't get this to work:
SELECT
CNTRSINTDATA.DIM_CNTRS_DATE_ENTITY.CALENDAR_MONTH
, CNTRSINTDATA.FACT_QUICKBOOKS_TRANS_TSI.TSI_NOMINAL_CODE
, CNTRSINTDATA.DIM_CNTRS_TSI_COA.TSI_NOMINAL_ACC
, CNTRSINTDATA.DIM_CNTRS_DATE_ENTITY.CNTRS_FIN_YEAR
, SUM (CNTRSINTDATA.FACT_QUICKBOOKS_TRANS_TSI.QB_TRANS_AMOUNT) AS CNTRS_ACC_BUDGET
FROM
CNTRSINTDATA.FACT_QUICKBOOKS_TRANS_TSI
, CNTRSINTDATA.DIM_CNTRS_DATE_ENTITY
, CNTRSINTDATA.DIM_CNTRS_TSI_COA
WHERE
CNTRSINTDATA.FACT_QUICKBOOKS_TRANS_TSI.QB_TRANS_DATE = CNTRSINTDATA.DIM_CNTRS_DATE_ENTITY.CALENDAR_DATE
AND CNTRSINTDATA.DIM_CNTRS_DATE_ENTITY.CNTRS_FIN_YEAR LIKE '2017'
AND CNTRSINTDATA.FACT_QUICKBOOKS_TRANS_TSI.TSI_NOMINAL_CODE = CNTRSINTDATA.DIM_CNTRS_TSI_COA.TSI_NOMINAL_CODE
AND CNTRSINTDATA.FACT_QUICKBOOKS_TRANS_TSI.TSI_NOMINAL_CODE = '6598'
GROUP BY
CNTRSINTDATA.FACT_QUICKBOOKS_TRANS_TSI.TSI_NOMINAL_CODE
, CNTRSINTDATA.DIM_CNTRS_TSI_COA.TSI_NOMINAL_ACC
, CNTRSINTDATA.DIM_CNTRS_DATE_ENTITY.CALENDAR_MONTH
, CNTRSINTDATA.DIM_CNTRS_DATE_ENTITY.CNTRS_FIN_YEAR;`
The above query returns results for:
Feb-17 250
Jul-17 400
Jun-17 654
May-17 654
Oct-17 150
Nov-17 250
Aug-17 250
Sep-17
I need the rest of the months to also come back with zero's as there no transactions on the account that month.
Jan-17 0
Feb-17 250
Mar-17 0
Apr-17 0
Jul-17 400
Jun-17 654
May-17 654
Oct-17 150
Nov-17 250
Aug-17 250
Sep-17 0
Dec-17 0
There is a date table that has all the months as VARCHAR2 against date. Just cant get the right syntax. Can anyone help please?
Let's break that down and make it more manageable.
Firstly, translate that to SQL-92 join syntax and add some aliases
SELECT
dcde.CALENDAR_MONTH
, fqtt.TSI_NOMINAL_CODE
, dctc.TSI_NOMINAL_ACC
, dcde.CNTRS_FIN_YEAR
, SUM (fqtt.QB_TRANS_AMOUNT) AS CNTRS_ACC_BUDGET
FROM
CNTRSINTDATA.FACT_QUICKBOOKS_TRANS_TSI fqtt
INNER JOIN CNTRSINTDATA.DIM_CNTRS_DATE_ENTITY dcde
ON fqtt.QB_TRANS_DATE = dcde.CALENDAR_DATE
INNER JOIN CNTRSINTDATA.DIM_CNTRS_TSI_COA dctc
ON AND fqtt.TSI_NOMINAL_CODE = dctc.TSI_NOMINAL_CODE
WHERE
dcde.CNTRS_FIN_YEAR LIKE '2017'
AND
fqtt.TSI_NOMINAL_CODE = '6598'
GROUP BY
fqtt.TSI_NOMINAL_CODE
, dctc.TSI_NOMINAL_ACC
, dcde.CALENDAR_MONTH
, dcde.CNTRS_FIN_YEAR;
Next, you said that there exists a date record (presumably in CNTRSINTDATA.DIM_CNTRS_DATE_ENTITY), so swap that around
SELECT
dcde.CALENDAR_MONTH
, fqtt.TSI_NOMINAL_CODE
, dctc.TSI_NOMINAL_ACC
, dcde.CNTRS_FIN_YEAR
, SUM (fqtt.QB_TRANS_AMOUNT) AS CNTRS_ACC_BUDGET
FROM
CNTRSINTDATA.DIM_CNTRS_DATE_ENTITY dcde
INNER JOIN CNTRSINTDATA.FACT_QUICKBOOKS_TRANS_TSI fqtt
ON fqtt.QB_TRANS_DATE = dcde.CALENDAR_DATE
INNER JOIN CNTRSINTDATA.DIM_CNTRS_TSI_COA dctc
ON AND fqtt.TSI_NOMINAL_CODE = dctc.TSI_NOMINAL_CODE
WHERE
dcde.CNTRS_FIN_YEAR LIKE '2017'
AND
fqtt.TSI_NOMINAL_CODE = '6598'
GROUP BY
fqtt.TSI_NOMINAL_CODE
, dctc.TSI_NOMINAL_ACC
, dcde.CALENDAR_MONTH
, dcde.CNTRS_FIN_YEAR;
Finally, you don't actually want inner joins because that eliminates tuples where there is no match. In this case, you want a left join because you want to have the left value even if no value exists on the right. You also need to coalesce your sum expression to 0 because (for reasons I cannot fathom), the SQL standard defines the sum of a bunch records only containing null as null.
SELECT
dcde.CALENDAR_MONTH
, fqtt.TSI_NOMINAL_CODE
, dctc.TSI_NOMINAL_ACC
, dcde.CNTRS_FIN_YEAR
, COALESCE(SUM (fqtt.QB_TRANS_AMOUNT), 0) AS CNTRS_ACC_BUDGET
FROM
CNTRSINTDATA.DIM_CNTRS_DATE_ENTITY dcde
LEFT JOIN CNTRSINTDATA.FACT_QUICKBOOKS_TRANS_TSI fqtt
ON fqtt.QB_TRANS_DATE = dcde.CALENDAR_DATE
LEFT JOIN CNTRSINTDATA.DIM_CNTRS_TSI_COA dctc
ON AND fqtt.TSI_NOMINAL_CODE = dctc.TSI_NOMINAL_CODE
WHERE
dcde.CNTRS_FIN_YEAR LIKE '2017'
AND
fqtt.TSI_NOMINAL_CODE = '6598'
GROUP BY
fqtt.TSI_NOMINAL_CODE
, dctc.TSI_NOMINAL_ACC
, dcde.CALENDAR_MONTH
, dcde.CNTRS_FIN_YEAR;
Give that a try and see if it is what you want
#Adam G,
Thank you for your suggestion. I actually got an idea from your commentry and instead created a select statement to get all the months I needed first. After that I joined to a select statement picking up the transactions where months matched and it worked. See below (come table names have changed)
SELECT DISTINCT
CNTRS_DATE_ENTITY.CALENDAR_MONTH
, CNTRS_DATE_ENTITY.CNTRS_FIN_MONTH_POS
, COALESCE (TRANS_DATA.TRANS_AMOUNT,0) AS TRANS_AMOUNT
FROM
CNTRSINTDATA.DIM_CNTRS_DATE_ENTITY CNTRS_DATE_ENTITY
LEFT JOIN
(
SELECT
QBS_TRANS_TSI.QB_NOMINAL_CODE
, TO_CHAR(QBS_TRANS_TSI.QB_TRANS_DATE, 'Mon-YY') AS TRANS_MONTH
, COALESCE (SUM(QBS_TRANS_TSI.QB_TRANS_AMOUNT),0) AS TRANS _AMOUNT
FROM
CNTRSINTDATA.FACT_QBS_TRANS_TSI QBS_TRANS_TSI
WHERE
QBS_TRANS_TSI.TSI_NOMINAL_CODE = '6598'
GROUP BY
QBS_TRANS_TSI.QB_NOMINAL_CODE
, TO_CHAR(QBS_TRANS_TSI.QB_TRANS_DATE, 'Mon-YY')
) TRANS_DATA
ON TRANS_DATA.TRANS_MONTH = CNTRS_DATE_ENTITY.CALENDAR_MONTH
WHERE
CNTRS_DATE_ENTITY.CNTRS_FIN_YEAR LIKE '2017'
ORDER BY
CNTRS_DATE_ENTITY.CNTRS_FIN_MONTH_POS
However the results have all the months but have blanks in the entity columns where the sum is zero. Any ideas on a remedy for this?
Here is one possible solution:
Generate fake empty transactions for the target period
for example using CTE:
declare #StartDate datetime = '20170101'
declare #EndDate datetime = '20171231'
;
with dt as
(
select #StartDate As 'thedate'
union all
select dateadd(month, 1, thedate) from dt where thedate < dateadd(month, -1, #EndDate)
)
select
dt.thedate 'row date',
datename(month,dt.thedate) 'Month',
YEAR(dt.thedate) 'Year',
0 'Amount '
from dt
Now you can add them to the transaction table (like union all) or you can do a left join with filtering on the result of your query.
I hope it helps! 🙂

SQL Query in CRM Report

A "Case" in CRM has a field called "Status" with four options.
I'm trying to
build a report in CRM that fills a table with every week of the year (each row is a different week), and then counts the number of cases that have each Status option (the columns would be each of the Status options).
The table would look like this
Status 1 Status 2 Status 3
Week 1 3 55 4
Week 2 5 23 5
Week 3 14 11 33
So far I have the following:
SELECT
SUM(case WHEN status = 1 then 1 else 0 end) Status1,
SUM(case WHEN status = 2 then 1 else 0 end) Status2,
SUM(case WHEN status = 3 then 1 else 0 end) Status3,
SUM(case WHEN status = 4 then 1 else 0 end) Status4,
SUM(case WHEN status = 5 then 1 else 0 end) Status5
FROM [DB].[dbo].[Contact]
Which gives me the following:
Status 1 Status 2 Status 3
2 43 53
Now I need to somehow split this into 52 rows for the past year and filter these results by date (columns in the Contact table). I'm a bit new to SQL queries and CRM - any help here would be much appreciated.
Here is a SQLFiddle with my progress and sample data: http://sqlfiddle.com/#!2/85b19/1
Sounds like you want to group by a range. The trick is to create a new field that represents each range (for you one per year) and group by that.
Since it also seems like you want an infinite range of dates, marc_s has a good summary for how to do the group by trick with dates in a generic way: SQL group by frequency within a date range
So, let's break this down:
You want to make a report that shows, for each contact, a breakdown, week by week, of the number of cases registered to that contact, which is divided into three columns, one for each StateCode.
If this is the case, then you would need to have 52 date records (or so) for each contact. For calendar like requests, it's always good to have a separate calendar table that lets you query from it. Dan Guzman has a blog entry that creates a useful calendar table which I'll use in the query.
WITH WeekNumbers AS
(
SELECT
FirstDateOfWeek,
-- order by first date of week, grouping calendar year to produce week numbers
WeekNumber = row_number() OVER (PARTITION BY CalendarYear ORDER BY FirstDateOfWeek)
FROM
master.dbo.Calendar -- created from script
GROUP BY
FirstDateOfWeek,
CalendarYear
), Calendar AS
(
SELECT
WeekNumber =
(
SELECT
WeekNumber
FROM
WeekNumbers WN
WHERE
C.FirstDateOfWeek = WN.FirstDateOfWeek
),
*
FROM
master.dbo.Calendar C
WHERE
CalendarDate BETWEEN '1/1/2012' AND getutcdate()
)
SELECT
C.FullName,
----include the below if the data is necessary
--Cl.WeekNumber,
--Cl.CalendarYear,
--Cl.FirstDateOfWeek,
--Cl.LastDateOfWeek,
'Week: ' + CAST(Cl.WeekNumber AS VARCHAR(20))
+ ', Year: ' + CAST(Cl.CalendarYear AS VARCHAR(20)) WeekNumber
FROM
CRM.dbo.Contact C
-- use a cartesian join to produce a table list
CROSS JOIN
(
SELECT
DISTINCT WeekNumber,
CalendarYear,
FirstDateOfWeek,
LastDateOfWeek
FROM
Calendar
) Cl
ORDER BY
C.FullName,
Cl.WeekNumber
This is different from the solution Ben linked to because Marc's query only returns weeks where there is a matching value, whereas you may or may not want to see even the weeks where there is no activity.
Once you have your core tables of contacts split out week by week as in the above (or altered for your specific time period), you can simply add a subquery for each StateCode to see the breakdown in columns as in the final query below.
WITH WeekNumbers AS
(
SELECT
FirstDateOfWeek,
WeekNumber = row_number() OVER (PARTITION BY CalendarYear ORDER BY FirstDateOfWeek)
FROM
master.dbo.Calendar
GROUP BY
FirstDateOfWeek,
CalendarYear
), Calendar AS
(
SELECT
WeekNumber =
(
SELECT
WeekNumber
FROM
WeekNumbers WN
WHERE
C.FirstDateOfWeek = WN.FirstDateOfWeek
),
*
FROM
master.dbo.Calendar C
WHERE
CalendarDate BETWEEN '1/1/2012' AND getutcdate()
)
SELECT
C.FullName,
--Cl.WeekNumber,
--Cl.CalendarYear,
--Cl.FirstDateOfWeek,
--Cl.LastDateOfWeek,
'Week: ' + CAST(Cl.WeekNumber AS VARCHAR(20)) +', Year: ' + CAST(Cl.CalendarYear AS VARCHAR(20)) WeekNumber,
(
SELECT
count(*)
FROM
CRM.dbo.Incident I
INNER JOIN CRM.dbo.StringMap SM ON
I.StateCode = SM.AttributeValue
INNER JOIN
(
SELECT
DISTINCT ME.Name,
ME.ObjectTypeCode
FROM
CRM.MetadataSchema.Entity ME
) E ON
SM.ObjectTypeCode = E.ObjectTypeCode
WHERE
I.ModifiedOn >= Cl.FirstDateOfWeek
AND I.ModifiedOn < dateadd(day, 1, Cl.LastDateOfWeek)
AND E.Name = 'incident'
AND SM.AttributeName = 'statecode'
AND SM.LangId = 1033
AND I.CustomerId = C.ContactId
AND SM.Value = 'Active'
) ActiveCases,
(
SELECT
count(*)
FROM
CRM.dbo.Incident I
INNER JOIN CRM.dbo.StringMap SM ON
I.StateCode = SM.AttributeValue
INNER JOIN
(
SELECT
DISTINCT ME.Name,
ME.ObjectTypeCode
FROM
CRM.MetadataSchema.Entity ME
) E ON
SM.ObjectTypeCode = E.ObjectTypeCode
WHERE
I.ModifiedOn >= Cl.FirstDateOfWeek
AND I.ModifiedOn < dateadd(day, 1, Cl.LastDateOfWeek)
AND E.Name = 'incident'
AND SM.AttributeName = 'statecode'
AND SM.LangId = 1033
AND I.CustomerId = C.ContactId
AND SM.Value = 'Resolved'
) ResolvedCases,
(
SELECT
count(*)
FROM
CRM.dbo.Incident I
INNER JOIN CRM.dbo.StringMap SM ON
I.StateCode = SM.AttributeValue
INNER JOIN
(
SELECT
DISTINCT ME.Name,
ME.ObjectTypeCode
FROM
CRM.MetadataSchema.Entity ME
) E ON
SM.ObjectTypeCode = E.ObjectTypeCode
WHERE
I.ModifiedOn >= Cl.FirstDateOfWeek
AND I.ModifiedOn < dateadd(day, 1, Cl.LastDateOfWeek)
AND E.Name = 'incident'
AND SM.AttributeName = 'statecode'
AND SM.LangId = 1033
AND I.CustomerId = C.ContactId
AND SM.Value = 'Canceled'
) CancelledCases
FROM
CRM.dbo.Contact C
CROSS JOIN
(
SELECT
DISTINCT WeekNumber,
CalendarYear,
FirstDateOfWeek,
LastDateOfWeek
FROM
Calendar
) Cl
ORDER BY
C.FullName,
Cl.WeekNumber