xQuery - Returning MAX Row - tsql

I'm pulling what hair I have left out! The resultset is all good but I now need to do something else. Here's the T-SQL
SELECT documentdate
, x.a.value('(Date)[1]','varchar(50)') as [Date]
, x.a.value('(ReadCode)[1]','varchar(50)') as [Read Code]
, x.a.value('(Rubric)[1]','varchar(200)') as [Rubric]
, x.a.value('(Notes)[1]','varchar(200)') as [Notes]
, x.a.value('(Notes1)[1]','varchar(200)') as [Notes1]
, x.a.value('(Episodicity)[1]','varchar(50)') as [Episodicity]
, REF.dbo.PATs.OptedOut
FROM
EPR.dbo.PCTX_CONT t INNER JOIN
REF.dbo.PATNumbers
ON t.PATNoID = REF.dbo.PATNumbers.PATNoID
INNER JOIN
REF.dbo.PATs ON
REF.dbo.PATNumbers.CurrentNo =
REF.dbo.PATs.ManorNo
CROSS APPLY
t.DocumentXML.nodes('//CONT') x(a)
WHERE REPLACE(REF.dbo.PATNumbers.CurrentNo,' ','')=123456789
The results are
2010-05-13 8I64.
2010-05-13 8I6C.
2010-02-09 8I24.
2010-02-09 8I65.
2010-02-09 8I26.
2010-02-09 8I6B.
2009-06-02 8I24.
2009-03-17 8I26.
2009-01-06 8I64.
2009-01-06 8I6C.
2006-11-14 8I74.
2006-11-14 8I75.
However what I need is the latest row for a code so the results would read
2010-05-13 8I64.
2010-05-13 8I6C.
2010-02-09 8I24.
2010-02-09 8I65.
2010-02-09 8I26.
2010-02-09 8I6B.
2006-11-14 8I74.
2006-11-14 8I75.

I am guessing that your codes are the Rubric column
select documentdate,[Date], [Read Code], [Rubric], [Notes], [Notes1],
[Episodicity],REF.dbo.PATs.OptedOut FROM
(
SELECT documentdate
, x.a.value('(Date)[1]','varchar(50)') as [Date]
, x.a.value('(ReadCode)[1]','varchar(50)') as [Read Code]
, x.a.value('(Rubric)[1]','varchar(200)') as [Rubric]
, x.a.value('(Notes)[1]','varchar(200)') as [Notes]
, x.a.value('(Notes1)[1]','varchar(200)') as [Notes1]
, x.a.value('(Episodicity)[1]','varchar(50)') as [Episodicity]
, REF.dbo.PATs.OptedOut
, row_number() over (partition by x.a.value('(Rubric)[1]','varchar(200)')
order by x.a.value('(Date)[1]','varchar(50)') desc) as rn
FROM
EPR.dbo.PCTX_CONT t INNER JOIN
REF.dbo.PATNumbers
ON t.PATNoID = REF.dbo.PATNumbers.PATNoID
INNER JOIN
REF.dbo.PATs ON
REF.dbo.PATNumbers.CurrentNo =
REF.dbo.PATs.ManorNo
CROSS APPLY
t.DocumentXML.nodes('//CONT') x(a)
WHERE REPLACE(REF.dbo.PATNumbers.CurrentNo,' ','')=123456789
) a where rn = 1

Related

How to repeat some data points in query results?

I am trying to get the max date by account from 3 different tables and view those dates side by side. I created a separate query for each table, merged the results with UNION ALL, and then wrapped all that in a PIVOT.
The first 2 sections in the link/pic below show what I have been able to accomplish and the 3rd section is what I would like to do.
Query results by step
How can I get the results from 2 of the tables to repeat? Is that possible?
--define var_ent_type = 'ACOM'
--define var_ent_id = '52766'
--define var_dict_id = 113
SELECT
*
FROM
(
SELECT
E.ENTITY_TYPE,
E.ENTITY_ID,
'PERF_SUMMARY' as "TableName",
PS.DICTIONARY_ID,
to_char(MAX(PS.END_EFFECTIVE_DATE), 'YYYY-MM-DD') as "MaxDate"
FROM
RULESDBO.ENTITY E
INNER JOIN PERFORMDBO.PERF_SUMMARY PS ON (PS.ENTITY_ID = E.ENTITY_ID)
WHERE
1=1
-- AND E.ENTITY_TYPE = '&var_ent_type'
-- AND E.ENTITY_ID = '&var_ent_id'
AND PS.DICTIONARY_ID >= 100
AND (E.ACTIVE_STATUS <> 'N' )--and E.TERMINATION_DATE is null )
GROUP BY
E.ENTITY_TYPE,
E.ENTITY_ID,
'PERF_SUMMARY',
PS.DICTIONARY_ID
union all
SELECT
E.ENTITY_TYPE,
E.ENTITY_ID,
'POSITION' as "TableName",
0 as DICTIONARY_ID,
to_char(MAX(H.EFFECTIVE_DATE), 'YYYY-MM-DD') as "MaxDate"
FROM
RULESDBO.ENTITY E
INNER JOIN HOLDINGDBO.POSITION H ON (H.ENTITY_ID = E.ENTITY_ID)
WHERE
1=1
-- AND E.ENTITY_TYPE = '&var_ent_type'
-- AND E.ENTITY_ID = '&var_ent_id'
AND (E.ACTIVE_STATUS <> 'N' )--and E.TERMINATION_DATE is null )
GROUP BY
E.ENTITY_TYPE,
E.ENTITY_ID,
'POSITION',
1
union all
SELECT
E.ENTITY_TYPE,
E.ENTITY_ID,
'CASH_ACTIVITY' as "TableName",
0 as DICTIONARY_ID,
to_char(MAX(C.EFFECTIVE_DATE), 'YYYY-MM-DD') as "MaxDate"
FROM
RULESDBO.ENTITY E
INNER JOIN CASHDBO.CASH_ACTIVITY C ON (C.ENTITY_ID = E.ENTITY_ID)
WHERE
1=1
-- AND E.ENTITY_TYPE = '&var_ent_type'
-- AND E.ENTITY_ID = '&var_ent_id'
AND (E.ACTIVE_STATUS <> 'N' )--and E.TERMINATION_DATE is null )
GROUP BY
E.ENTITY_TYPE,
E.ENTITY_ID,
'CASH_ACTIVITY',
1
--ORDER BY
-- 2,3, 4
)
PIVOT
(
MAX("MaxDate")
FOR "TableName"
IN ('CASH_ACTIVITY', 'PERF_SUMMARY','POSITION')
)
Everything is possible. You only need a window function to make the value repeat across rows w/o data.
--Assuming current query is QC
With QC as (
...
)
select code, account, grouping,
--cash,
first_value(cash) over (partition by code, account order by grouping asc rows unbounded preceding) as cash_repeat,
perf,
--pos,
first_value(pos) over (partition by code, account order by grouping asc rows unbounded preceding) as pos_repeat
from QC
;
See first_value() help here: https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/FIRST_VALUE.html#GUID-D454EC3F-370C-4C64-9B11-33FCB10D95EC

Change column value after left join SQL

I have the following statement:
select distinct x_order.code , x_order.status , x_order.project , project.active , project.code as projectcode
from project
left join x_order on x_order.project = project.code
where status = 'B' and active = 0
Which gives me a nice table with all the records I want to change. I now need to change the values in the 'status' column from B to D in this table. How can I do that?
I tried UPDATE, but to no success.
Not sure of the exact table structures you're using, but would a CTE work for you like this...
;WITH CTE
AS (
select distinct x_order.code as ordercode , x_order.status , x_order.project , project.active , project.code as projectcode
from project
left join x_order on x_order.project = project.code
where status = 'B' and active = 0
)
UPDATE X
SET [status] = 'D'
FROM x_order X
JOIN CTE C
ON X.code = C.ordercode

SQL - Rank or Row_Number not bringing back desired data

I'm writing a query that will bring me back either row or rank '1'. When I run the query with the 'where rank or row clause equals 1', no data returns for those columns but if I take out the 'where rank or row clause' the data populates. Can someone tell me why the where clause is causing no data to return?
LEFT OUTER JOIN
(SELECT DISTINCT CLMED.SIMPLE_GENERIC_C
, MEDINFO.MEDICATION_ID as [CYTOTEC]
,FMED.PAT_ENC_CSN_ID
, FMED.HOSP_ADMSN_DATE
-- , MIN(FMED.TAKEN_DATETIME) over (Partition by FMED.PAT_ENC_CSN_ID,
MEDINFO.MEDICATION_ID ) as 'FIRST DOSE'
, MIN(FMED.TAKEN_DATETIME) over (Partition by FMED.PAT_ENC_CSN_ID, CLMED.SIMPLE_GENERIC_C
) AS 'FIRST DOSE'
, RANK() over (Partition by FMED.PAT_ENC_CSN_ID, CLMED.SIMPLE_GENERIC_C order by
FMED.TAKEN_DATETIME DESC) 'CYTOTEC_RANK'
, ROW_NUMBER() over (Partition by FMED.PAT_ENC_CSN_ID, MEDINFO.MEDICATION_ID order by
FMED.TAKEN_DATETIME) AS 'CYTOTEC_ROW'
, FMED.DISPLAY_NAME
, FMED.ORDER_MED_ID
, ORDMED.DESCRIPTION
, ZCGEN.NAME
FROM MED_ADMIN FMED
LEFT JOIN MEDINFO MEDINFO ON FMED.ORDER_MED_ID = MEDINFO.ORDER_MED_ID
LEFT JOIN MED ORDMED ON FMED.ORDER_MED_ID = ORDMED.ORDER_MED_ID
LEFT JOIN MEDICATION CLMED ON MEDINFO.MEDICATION_ID = CLMED.MEDICATION_ID
LEFT JOIN GENERIC ZCGEN ON CLMED.SIMPLE_GENERIC_C = ZCGEN.SIMPLE_GENERIC_C
WHERE ZCGEN.NAME = 'miSOPROStol'
AND 'CYTOTEC_RANK' = 1
) AS [CYT] ON CYT.PAT_ENC_CSN_ID = VITALS.PAT_ENC_CSN_ID

SQL 2008 cumulative count

I have a query returning the number of rows grouped by date :
SELECT convert(date, run.TimeStamp) as TimeStamp, count(*)
FROM ScriptResult AS res INNER JOIN
ScriptRun AS run ON run.ScriptRunID = res.ScriptRunID INNER JOIN
WorkListItems AS wli ON wli.WorkListItemID = res.WorklistItemID INNER JOIN
WorkList AS wl ON wl.WorkListID = wli.WorkListID
WHERE (wli.WorkListID = #WLID)
GROUP by convert(date, run.TimeStamp)
ORDER BY convert(date, run.TimeStamp);
This produces a result set like this :
TimeStamp (ItemCount)
2015-03-10 5364
2015-03-11 22027
2015-03-12 18037
Now what I want, is to cumulatively summarize the itemcount, like this :
TimeStamp ItemCount TotalCount
2015-03-10 5364 5364
2015 -03-11 22027 27391
2015-03-12 18037 45428
The query needs to be compatible with 2008R2.
I have played with [count ...over..partition by] in several variations but the problem is that the window function boundary should chage. And I cannot use ROWS or RANGE.
Any ideas please ?
Thanks in advance.
Try with correlated subquery:
;WITH cte as(
SELECT convert(date, run.TimeStamp) as TimeStamp, count(*) AS S
FROM ScriptResult AS res INNER JOIN
ScriptRun AS run ON run.ScriptRunID = res.ScriptRunID INNER JOIN
WorkListItems AS wli ON wli.WorkListItemID = res.WorklistItemID INNER JOIN
WorkList AS wl ON wl.WorkListID = wli.WorkListID
WHERE (wli.WorkListID = #WLID)
GROUP by convert(date, run.TimeStamp)
)
SELECT TimeStamp,
S,
(SELECT SUM(S) FROM cte t2 WHERE t2.TimeStamp <= t1.TimeStamp) AS TS
FROM cte t1
You could try creating a temp table to hold the first query results that you can further aggregate to return the cumulative sum on the ItemCount field:
CREATE TABLE #TempTable(
[SeqNo] [int] NULL,
[TimeStamp] [Date] NULL,
[ItemCount] [int] NULL
) ON [PRIMARY]
SELECT
ROW_NUMBER() OVER (PARTITION BY res.ScriptRunID ORDER BY run.TimeStamp) AS SeqNo,
CONVERT(Date, run.TimeStamp) AS TimeStamp,
COUNT(*) AS ItemCount
INTO #TempTable
FROM ScriptResult AS res
INNER JOIN ScriptRun AS run
ON run.ScriptRunID = res.ScriptRunID
INNER JOIN WorkListItems AS wli
ON wli.WorkListItemID = res.WorklistItemID
INNER JOIN WorkList AS wl
ON wl.WorkListID = wli.WorkListID
WHERE (wli.WorkListID = #WLID)
GROUP BY CONVERT(Date, run.TimeStamp)
ORDER BY CONVERT(Date, run.TimeStamp);
SELECT
t1.TimeStamp,
t1.ItemCount,
SUM(t2.ItemCount) AS TotalCount
FROM #TempTable AS t1
INNER JOIN #TempTable AS t2
on t1.SeqNo >= t2.SeqNo
GROUP BY t1.TimeStamp, t1.ItemCount
ORDER BY t1.TimeStamp
SQL Fiddle Example
Note: This links to a Microsoft SQL Server 2014 database version SQL fiddle which should work with SQL Server 2008 as well.

SQL Column Populating

I want to know if it is possible to create another column in a table that has data that I wish to populate in this new column? The new column is Flag2. Here is the table:
what I want to do is, where item id is 30, I want the ITEM ID to only display 30 once and, populate the QC Unsupportted in Flag2? How do I do this?
I can only think of doing an inner join but this is not working.
This is what I have done in trying to do so:
SELECT
A.ITEMID, A.FLAG1, A.FLAG2
FROM
#FLAGS as A
INNER JOIN
#FLAGS as B ON A.ITEMID = B.ITEMID
GROUP BY
a.ITEMID, a.FLAG1, A.FLAG2
ORDER BY
ITEMID
Assuming I understand what you are after, if the current FLAG1 values are distinct for any ITEMID and you only have at most two instances of the same ID, I think this should do what you want:
SELECT
lft.ITEMID
, lft.FLAG1
, rght.FLAG1 FLAG2
FROM (
SELECT
t.ITEMID
, t.FLAG1
FROM (
SELECT
l.ITEMID
, l.FLAG1
, COUNT(l.ITEMID) i
FROM #FLAGS l
INNER JOIN #FLAGS r ON l.ITEMID = r.ITEMID
WHERE r.FLAG1 <= l.FLAG1
GROUP BY
l.ITEMID
, l.FLAG1) t
WHERE t.i=1) lft
LEFT OUTER JOIN (
SELECT
t.ITEMID
, t.FLAG1
FROM (
SELECT
l.ITEMID
, l.FLAG1
, COUNT(l.ITEMID) i
FROM #FLAGS l
INNER JOIN #FLAGS r ON l.ITEMID = r.ITEMID
WHERE r.FLAG1 <= l.FLAG1
GROUP BY
l.ITEMID
, l.FLAG1) t
WHERE t.i=2) rght ON lft.ITEMID = rght.ITEMID
-- Or better
SELECT
lft.ITEMID
, lft.FLAG1
, rght.FLAG1 FLAG2
FROM (
SELECT
t.ITEMID
, t.FLAG1
FROM (
SELECT
l.ITEMID
, l.FLAG1
, ROW_NUMBER() OVER(PARTITION BY ITEMID ORDER BY FLAG1) as i
FROM test l) t
WHERE t.i=1) lft
LEFT OUTER JOIN (
SELECT
t.ITEMID
, t.FLAG1
FROM (
SELECT
l.ITEMID
, l.FLAG1
, ROW_NUMBER() OVER(PARTITION BY ITEMID ORDER BY FLAG1) as i
FROM test l) t
WHERE t.i=2) rght ON lft.ITEMID = rght.ITEMID
If you have additional flag values for the same ID, a new outer join can be added to a new inline table (rght2, rght3, etc.) where i=3, 4, etc. and you are selecting rght2 AS FLAG3, rght3 AS FLAG4, etc.
Also note that the current values for FLAG1 will be distributed through FLAG1 and FLAG2 in alphabetical order. If you wanted to distribute them in reverse order you could replace <= with >=. If you had more than two flags that you wanted distributed in a specific order, you would have to create a separate table with a ranking value and join to that which would be doable but even uglier!