First event per patients - sql

The attached code is supposed to return the first ORDER_PROC.ORDER_INST for each patient. I'm getting multiple records in some cases.
Any suggestions on a better approach?
Thanks
Steve
SELECT DISTINCT
ORDER_PROC.PAT_ENC_CSN_ID as ordercsn, Min(ORDER_PROC.ORDER_INST) as
CodeStatus_Datetime, CLARITY_SER.PROV_NAME as CodeStatus_OrderProvider
FROM
ORDER_PROC with(nolock) , ORDER_METRICS with(nolock) , CLARITY_SER
with(nolock)
WHERE
ORDER_PROC.ORDER_PROC_ID = ORDER_METRICS.ORDER_ID AND
ORDER_METRICS.ORDERING_PROV_ID = CLARITY_SER.PROV_ID AND
--ORDER_PROC.REASON_FOR_CANC_C IS NULL AND
(ORDER_PROC.PROC_CODE = 'COD1' OR
ORDER_PROC.PROC_CODE = 'COD2' OR
ORDER_PROC.PROC_CODE = 'COD3'
)
GROUP by
ORDER_PROC.PAT_ENC_CSN_ID, ORDER_PROC.ORDER_INST,CLARITY_SER.PROV_NAME

Use ROW_NUMBER() to create partition for each patient
SELECT *
FROM (
SELECT OP.PAT_ENC_CSN_ID as ordercsn,
OP.ORDER_INST,
CodeStatus_Datetime,
CS.PROV_NAME as CodeStatus_OrderProvider,
ROW_NUMBER() OVER (PARTITION BY OP.PAT_ENC_CSN_ID
ORDER BY OP.ORDER_INST) as rn
FROM ORDER_PROC OP
JOIN ORDER_METRICS OM
OP.ORDER_PROC_ID = OM.ORDER_ID
JOIN CLARITY_SER CS
OM.ORDERING_PROV_ID = CS.PROV_ID
WHERE
OP.PROC_CODE IN ('COD1','COD2','COD3')
) as T
WHERE rn = 1

Related

SQL Server aggregate function without group by

I want to include tcon.Inductive_Injection_Hours, tcon.Capacitive_Injection_Hours without applying group by. How can I do that?
SELECT
bp.Serial_Number,
tcon.Serial_Number AS ConverterSerialNumber,
MAX(tcon.Time_Stamp) AS DateStamp,
tcon.Inductive_Injection_Hours,
tcon.Capacitive_Injection_Hours
FROM
dbo.Bypass AS bp
INNER JOIN
dbo.Converter AS c ON bp.Bypass_ID = c.Bypass_ID
INNER JOIN
dbo.Converter_Tel_Data AS tcon ON c.Converter_ID = tcon.Converter_ID
WHERE
(bp.Site_ID = 7)
GROUP BY
bp.Serial_Number, tcon.Serial_Number,
tcon.Inductive_Injection_Hours, tcon.Capacitive_Injection_Hours
ORDER BY
ConverterSerialNumber
I have figured it out.
select [data].Serial_Number,Time_Stamp,Inductive_Injection_Hours,Capacitive_Injection_Hours,b.Serial_Number from Converter_Tel_Data as [data]
inner join dbo.Converter AS c On [data].Converter_ID = c.Converter_ID
inner join dbo.Bypass as b on c.Bypass_ID = b.Bypass_ID
WHERE
(Time_Stamp = (SELECT MAX(Time_Stamp) FROM Converter_Tel_Data WHERE Converter_ID = [data].Converter_ID)) And ([data].Site_ID=7)
ORDER BY [data].Serial_Number
You can use row_number - either in a CTE/derived table or using a trick with TOP 1.
Select Top 1 With Ties
bp.Serial_Number
, tcon.Serial_Number AS ConverterSerialNumber
, tcon.Time_Stamp AS DateStamp
, tcon.Inductive_Injection_Hours
, tcon.Capacitive_Injection_Hours
From dbo.Bypass AS bp
Inner Join dbo.Converter AS c On bp.Bypass_ID = c.Bypass_ID
Inner Join dbo.Converter_Tel_Data AS tcon ON c.Converter_ID = tcon.Converter_ID
Where bp.Site_ID = 7
Order By
row_number() over(Partition By bp.Serial_Number Order By tcon.Time_Stamp desc)
This should return the latest row from the tconn table for each bp.Serial_Number.

SQL - Show all values from the first tabel

I want to show all values of a column 'nation.nationen_bez' in the tabel 'nation' using this query:
SELECT DISTINCT nation.nationen_bez,
NVL(SUM (debitor.flimit_deb) OVER (PARTITION BY nation.nationen_bez ORDER BY nation.nationen_bez),0) AS korisceno,
NVL(nation_ext.country_limit,0) - NVL(SUM (debitor.flimit_deb) OVER (PARTITION BY nation.nationen_bez ORDER BY nation.nationen_bez),0) AS se_na_voljo,
NVL(nation_ext.country_limit,0) AS odobren_limit
FROM debitor,
nation,
nation_ext,
firmenstamm,
debitorenstamm
WHERE ( nation.nationen_kode = debitorenstamm.nationen_kode (+)) and
( nation.nationen_id = nation_ext.nationen_id (+)) and
( debitor.debitoren_id = debitorenstamm.debitoren_id ) and
( debitorenstamm.waehrungs_id = firmenstamm.waehrungs_id ) and
( ( debitor.risiko = 1 ) AND
( debitor.factoringart = 'EF' ))
With this query I get only those 'nation.nationen_bez' where exist debitors with debitor.risiko = 1 and
debitor.factoringart = 'EF'. This conditioin is needed for 'NVL(SUM (debitor.flimit_deb) OVER (PARTITION BY nation.nationen_bez ORDER BY nation.nationen_bez),0) AS korisceno', because I want sum only 'flimit_deb' for those debtors that have debitor.risiko = 1 and debitor.factoringart = 'EF' - how can I change this state?
tnx in advance
I have used left join, started with nation
SELECT DISTINCT nation.nationen_bez,
SUM (debitor.flimit_deb) OVER (PARTITION BY nation.nationen_bez ORDER BY nation.nationen_bez) AS korisceno,
nation_ext.country_limit - SUM (debitor.flimit_deb) OVER (PARTITION BY nation.nationen_bez ORDER BY nation.nationen_bez) AS se_na_voljo,
nation_ext.country_limit AS odobren_limit
FROM nation
left join debitorenstamm on nation.nationen_kode = debitorenstamm.nationen_kode
left join debitor on debitorenstamm.debitoren_id = debitor.debitoren_id and debitor.risiko = 1 AND debitor.factoringart = 'EF'
left join nation_ext on nation.nationen_id = nation_ext.nationen_id
left join firmenstamm on debitorenstamm.waehrungs_id = firmenstamm.waehrungs_id

SQL Select 1 line in function of 3 MAX/MIN fields

I try to create a view, or just a select for the moment, based on this function :
SELECT
FLAG
FROM
(
SELECT
TE.FLAG
FROM
EVT E
INNER JOIN EVT_TYP TE ON TE.ID = E.FK_TYPE_EVT
WHERE
E.FK_OBJECT = NUMOBJECT
order by
trunc(E.EVT_DATE) desc,
e.evt_number desc,
e.id desc
)
where
rownum = 1;
NUMOBJECT is the function parameter. Function returns one FLAG for that NUMOBJECT.
I want to select one flag for each E.FK_OBJECT IN EVT table.
Problems are I can have several lines in EVT table for one E.FK_OBJECT the same day, and I don't have time part of the date, most of the time. E.evt_number can be int or NULL. And E.id haven't the same order that E.EVT_DATE.
I don't know how I can succeed it, can you help me please? I try with imbricates select but looks likes it's not possible beacause of NULL e.evt_number.
I work on Oracle DB.
edit :
Sample of data :
Heberger image http://img15.hostingpics.net/thumbs/mini_229922Sanstitre.png
I tried this :
SELECT E.Fk_Object
,TE.FLAG
FROM (
SELECT
E.Fk_Object
,E.EVT_DATE
,E.evt_number
,MAX(E.id) id
FROM (
SELECT
E.Fk_Object
,E.EVT_DATE
,MAX(NVL(e.evt_number, - 1)) evt_number
FROM (
SELECT
E.Fk_Object
,MAX(E.EVT_DATE) EVT_DATE
FROM EVT E
GROUP BY E.Fk_Object
) E_MAX
INNER JOIN EVT E ON E.Fk_Object = E_MAX.Fk_Object
AND E.EVT_DATE = E_MAX.EVT_DATE
WHERE e.flg_suppression = 0
AND e.evt_date IS NOT NULL
GROUP BY E.Fk_Object
,E.EVT_DATE
) E_MAX_2
INNER JOIN EVT E ON E.Fk_Object = E_MAX_2.Fk_Object
AND E.EVT_DATE = E_MAX_2.EVT_DATE
AND NVL(e.evt_number, - 1) = NVL(E_MAX_2.evt_number, - 1)
GROUP BY E.Fk_Object
,E.EVT_DATE
,E.evt_number
) E_MAX_3
left JOIN EVT E ON E.Fk_Object = E_MAX_3.Fk_Object
AND E.EVT_DATE = E_MAX_3.EVT_DATE
AND NVL(e.evt_number, - 1) = NVL(E_MAX_3.evt_number, - 1)
AND E.id = E_MAX_3.id
INNER JOIN EVT_TYP TE ON TE.id = E.FK_EVT_TYP
ORDER BY 2
,3;
But it doesn't give me same results than function
Done !
Instead of NVL(E_MAX_2.evt_number, - 1) I have to use NVL(E_MAX_2.evt_number, 99) and not forget the trunc() for E.EVT_DATE to keep the same order than the function and it is ok !!
With that, it runs in 12 seconds. It was 54 before with the function.
I will test to create a view to see if it's even better.
If I understand correctly, you are looking for a query that gives you the latest flag for not only one, but several objects. You can do this by selecting records for all these objects and then grouping by object applying Oracle's KEEP FIRST/LAST.
select
e.fk_object,
max(te.flag) keep (dense_rank first
order by trunc(e.evt_date) desc, e.evt_number desc, e.id desc) as current_flag
from evt e
join evt_typ et on et.id = e.fk_type_evt
where fk_object in (numobject1, numobject2, numobject3)
group by e.fk_object;
The same can be used as a subquery. Let's say you have a table OBJECTS with a column STATUS and you want to show all objects of status 'new' with their current flag each:
select o.*, flags.current_flag
from objects o
join
(
select
e.fk_object,
max(te.flag) keep (dense_rank first
order by trunc(e.evt_date) desc, e.evt_number desc, e.id desc) as current_flag
from evt e
join evt_typ et on et.id = e.fk_type_evt
group by e.fk_object
) flags on flags.fk_object = o.id
where o.status = 'new';

how to insert random records without violating primary constraint

Please pardon my title if misleading, but I have a table tb_party with PRIMARY KEY on party_key
I have following query -
insert TMS..tb_party
(
[party_key]
,[party_first_name]
,[tax_id]
,[party_type_cd]
,[citizenship_country_cd]
,[domicile_country_cd]
,[party_num]
,[batch_dt]
)
select distinct
[party_key]
,[party_first_name]
,[tax_id]
,[party_type_cd]
,[cit]
,[dom]
,[party_num]
,[batch_dt]
from
(select distinct
sca.[party_key]
,sca.[party_first_name]
,sca.[tax_id]
,pt.party_type_cd
,tc_cit.COUNTRY_ID as cit
,tc_dom.COUNTRY_ID as dom
,sca.[party_num]
,getdate() as batch_dt
,dense_rank() over(partition by sca.[party_key] order by sca.party_key) as rnk
from Iteration_3.dbo.staging_cust_acct sca (nolock)
join Iteration_3..STG_PARTY_UPLOAD (nolock) stg_party
on sca.party_key = stg_party.PARTY_KEY
left join Iteration_3..STG_COUNTRY_ISO tc_dom (nolock)
on sca.[domicile_country] = tc_dom.COUNTRY_NAME
left join Iteration_3..STG_COUNTRY_ISO tc_cit (nolock)
on sca.[citizenship_country] = tc_cit.COUNTRY_NAME
left join TMS..tb_party_type pt (nolock)
on sca.[party_type] = pt.party_type_desc
WHERE
SCA.party_type IS NOT NULL
) x
where rnk = 1
The insert fails because it is trying to insert duplicate party key and since the distinct is on ALL columns, it is picking up duplicate party_keys.
What I want - I want to pick up all distinct party_keys and insert 1 row in tb_party. the other rows can be ignored. Is this possible?
Here is where row_number came in handy.
select distinct
[party_key]
,[party_first_name]
,[tax_id]
,[party_type_cd]
,[cit]
,[dom]
,[party_num]
,[batch_dt]
from
(
select distinct
sca.[party_key]
,sca.[party_first_name]
,sca.[tax_id]
,pt.party_type_cd
,tc_cit.COUNTRY_ID as cit
,tc_dom.COUNTRY_ID as dom
,sca.[party_num]
,getdate() as batch_dt
--,dense_rank() over(partition by sca.[party_key] order by sca.party_key,sca.[tax_id],sca.[party_num],sca.[party_first_name]*/) as rnk
,row_number() over (partition by sca.party_key order by sca.party_key) rn
from Iteration_3.dbo.staging_cust_acct sca (nolock)
join Iteration_3..STG_PARTY_UPLOAD (nolock) stg_party
on sca.party_key = stg_party.PARTY_KEY
left join Iteration_3..STG_COUNTRY_ISO tc_dom (nolock)
on sca.[domicile_country] = tc_dom.COUNTRY_NAME
left join Iteration_3..STG_COUNTRY_ISO tc_cit (nolock)
on sca.[citizenship_country] = tc_cit.COUNTRY_NAME
left join TMS..tb_party_type pt (nolock)
on sca.[party_type] = pt.party_type_desc
WHERE --SCA.update_source = 'ECM' AND SCA.update_dt = #ECM_MAX_DATE
--and
SCA.party_type IS NOT NULL
) x
where rn = 1
Try merging into your target table on the unique columns. When not matched, insert. When matched update like this:
...
set target.[column] = coalesce(source.[column], target.[column])
...
This way you update all your target columns when you have source values, otherwise they remain unchanged.)

how to get the latest price in sql query

I need get the price of lasted QuoteDate.
Right now i have query like these
SELECT dbo.INMT.Material, dbo.INMT.LastVendor, dbo.INMT.AvgCost, dbo.MSQD.Status, dbo.MSQH.QuoteDate, dbo.MSQD.UnitPrice
FROM dbo.INMT INNER JOIN
dbo.MSQD ON dbo.INMT.MatlGroup = dbo.MSQD.MatlGroup AND dbo.INMT.Material = dbo.MSQD.Material INNER JOIN
dbo.MSQH ON dbo.MSQD.MSCo = dbo.MSQH.MSCo AND dbo.MSQD.Quote = dbo.MSQH.Quote
GROUP BY dbo.INMT.Material, dbo.INMT.LastVendor, dbo.INMT.AvgCost, dbo.MSQD.Status, dbo.MSQD.UnitPrice, dbo.MSQH.QuoteDate
ORDER BY dbo.INMT.Material
and get the following result
and how can i run a query just get the highlighted record.i try to do something like where QuoteDate =max......but maybe my grouyping is not correct.
thanks
So, assuming SQL Server 2005+, you can use a CTE and ROW_NUMBER():
;WITH CTE AS
(
SELECT I.Material,
I.LastVendor,
I.AvgCost,
MD.Status,
MH.QuoteDate,
MD.UnitPrice,
RN = ROW_NUMBER() OVER( PARTITION BY I.Material, I.LastVendor,
I.AvgCost, MD.Status,
MD.UnitPrice
ORDER BY MH.QuoteDate DESC)
FROM dbo.INMT I
INNER JOIN dbo.MSQD MD
ON I.MatlGroup = MD.MatlGroup
AND I.Material = MD.Material
INNER JOIN dbo.MSQH MH
ON MD.MSCo = MH.MSCo
AND MD.Quote = MH.Quote
)
SELECT Material,
LastVendor,
AvgCost,
Status,
QuoteDate,
UnitPrice
FROM CTE
WHERE RN = 1
Use HAVING QuoteDate=max... after the order by clause.