header and details table query - sql

I have one master table from that I get encounter ids and a text and I have a detail table, matching fields are encounter id and text. from details table, I need to fetch the latest record as per the date and time and display.
I don't know how to do it. I'm thinking that top 1 should work.
select top 1 om.txt_order_enc_id, txt_act_text_display, txt_actionDate, txt_action from order_management_data_ om
inner join order_ o on om.txt_order_enc_id = o.encounterID
and om.txt_act_text_display = o.actTextDisplay
where o.actstatus = 'ordered'
and o.actclass = 'REFR'
and o.encounterdate < '20180610'
order by o.encounterdate desc
expected result.
latest record encounter id, text, status from detail table.

First create a group by on basis of encounterID. Create row index for same. And filter out the top 1 record of each group.
; with cte as (
select row_number () (partition by o.encounterID order by o.encounterdate desc) as Slno,
om.txt_order_enc_id, txt_act_text_display, txt_actionDate, txt_action from order_management_data_ om
inner join order_ o on om.txt_order_enc_id = o.encounterID
and om.txt_act_text_display = o.actTextDisplay
where o.actstatus = 'ordered'
and o.actclass = 'REFR'
and o.encounterdate < '20180610'
)
select * from cte where Slno = 1

Related

SQL query to return duplicate rows for certain column, but with unique values for another column

I have written the query shown here that combines three tables and returns rows where the at_ticket_num from appeal_tickets is duplicated but against a different at_sys_ref value
select top 100
t.t_reference, at.at_system_ref, at_ticket_num, a.a_case_ref
from
tickets t, appeal_tickets at, appeals_2 a
where
t.t_reference in ('AB123','AB234') -- filtering on these values so that I can see that its working
and t.t_number = at.at_ticket_num
and at.at_system_ref = a.a_system_ref
and at.at_ticket_num IN (select at_ticket_num
from appeal_tickets
group by at_ticket_num
having count(distinct at_system_ref) > 1)
order by
t.t_reference desc
This is the output:
t_reference at_system_ref at_ticket_num a_case_ref
-------------------------------------------------------
AB123 30838974 23641583 1111979010
AB123 30838976 23641583 1111979010
AB234 30839149 23641520 1111977352
AB234 30839209 23641520 1111988003
I want to modify this so that it only returns records where t_reference is duplicated but against a different a_case_ref. So in above case only records for AB234 would be returned.
Any help would be much appreciated.
You want all ticket appeals that have more than one system reference and more than one case reference it seems. You can join the tables, count the occurrences per ticket and then only keep the tickets that match these criteria.
select *
from
(
select
t.t_reference, at.at_system_ref, at.at_ticket_num, a.a_case_ref,
count(distinct a.a_system_ref) over (partition by at.at_ticket_num) as sysrefs,
count(distinct a.a_case_ref) over (partition by at.at_ticket_num) as caserefs
from tickets t
join appeal_tickets at on at.at_ticket_num = t.t_number
join appeals_2 a on a.a_system_ref = at.at_system_ref
) counted
where sysrefs > 1 and caserefs > 1
order by t.t_reference, at.at_system_ref, at.at_ticket_num, a.a_case_ref;
Correction
It seems that SQL Server still doesn't support COUNT(DISTINCT ...) OVER (...). You can count distinct values in a subquery though. Replace
count(distinct a.a_system_ref) over (partition by at.at_ticket_num) as sysrefs,
by
(
select count(distinct a2.a_system_ref)
from appeal_tickets at2
join appeals_2 a2 on a2.a_system_ref = at2.at_system_ref
where at2.at_ticket_num = t.t_number
) as sysrefs,
An alternative workaround is to use DENSE_RANK in two directions (found here: https://stackoverflow.com/a/53518204/2270762):
dense_rank() over (partition by at.at_ticket_num order by a.a_system_ref) +
dense_rank() over (partition by at.at_ticket_num order by a.a_system_ref desc) -
1 as sysrefs,
with data as (
<your query plus one column>,
case when
min() over (partition by t.t_reference)
<>
max() over (partition by t.t_reference)
then 1 end as dup
)
select * from data where dup = 1

Oracle - return only the first row for each product

In the first SELECT statement, the report grabs inv details for all products with shipment activity. There is then a UNION that connect another SELECT statement to grab products without activity from the last calendar year.
However, the records that are returned in the second SELECT statement have multiple header_id’s and therefore multiple lines… instead of single lines like the first SELECT statement. Do you know how to pull only the first header_id of each record in the second SELECT statement?
Code and example result set below. In data, product #7 should only list the row for header_id 1372288 which is the last ID entered into the DB.
select 3 sort_key, header_Id,location_id,nlasinv.product,
start_inv,produced produced_inv,stored,from_stock,shipped,
(start_inv + produced + stored) - (from_stock + shipped) end_inv,nlas_ops_mtd_prodsize(111,nlasinv.product,'31-DEC-19'), nlas_ops_mtd_shipsize(111,nlasinv.product,'31-DEC-19'),nlas_ops_ytd_prodsize(111,nlasinv.product,'31-DEC-19'), nlas_ops_ytd_shipsize(111,nlasinv.product,'31-DEC-19')
from nlas_header inv,
nlas_inventory nlasinv
where nlasinv.header_id = 1372168
and inv.id = nlasinv.header_id
union
select distinct
3 sort_key,header_Id,location_id,nlasinv.product,
start_inv,produced produced_inv,stored,from_stock,shipped,
(start_inv + produced + stored) - (from_stock + shipped) end_inv,nlas_ops_mtd_prodsize(111,nlasinv.product,'31-DEC-19'),
nlas_ops_mtd_shipsize(111,nlasinv.product,'31-DEC-19'),nlas_ops_ytd_prodsize(111,nlasinv.product,'31-DEC-19'),
nlas_ops_ytd_shipsize(111,nlasinv.product,'31-DEC-19')
from
nlas_inventory nlasinv,
nlas_header hdr
where
nlasinv.header_id = hdr.id
and hdr.location_id = 409
and hdr.observation_date >= trunc(to_date('31-DEC-19','dd-mon-rr'),'year')
and nlasinv.product not in
(select distinct product from
nlas_header h,
nlas_inventory i
where i.header_id = 1372168)
order by product, header_id des
c
I don't know what your query has to do with the "table" data that you show. But you seem to want row_number():
select t.*
from (select t.*, row_number() over (partition by product order by header_id desc) as seqnum
from t
) t
where seqnum = 1;
If that query is being used to generate the data, then just wrap it in a CTE.
This can also be accomplished by adding a self join in your where clause
and hdr.header_id = (
select max(hdr2.header_id)
from nlas_header hdr2
where hdr2.location_id = hdr.location_id
and hdr2.product_id = hdr.product_id)

Select all rows with max date for each ID

I have the following query returning the data as shown below. But I need to exclude the rows with MODIFIEDDATETIME shown in red as they have a lower time stamp by COMMITRECID. As depicted in the data, there may be multiple rows with the max time stamp by COMMITRECID.
SELECT REQCOMMIT.COMMITSTATUS, NOTEHISTORY.NOTE, NOTEHISTORY.MODIFIEDDATETIME, NOTEHISTORY.COMMITRECID
FROM REQCOMMIT INNER JOIN NOTEHISTORY ON REQCOMMIT.RECID = NOTEHISTORY.COMMITRECID
WHERE REQCOMMIT.PORECID = 1234
Here is the result of the above query
The desired result is only 8 rows with 5 in Green and 3 in Black (6 in Red should get eliminated).
Thank you very much for your help :)
Use RANK:
WITH CTE AS
(
SELECT R.COMMITSTATUS,
N.NOTE,
N.MODIFIEDDATETIME,
N.COMMITRECID,
RN = RANK() OVER(PARTITION BY N.COMMITRECID ORDER BY N.MODIFIEDDATETIME)
FROM REQCOMMIT R
INNER JOIN NOTEHISTORY N
ON R.RECID = N.COMMITRECID
WHERE R.PORECID = 1234
)
SELECT *
FROM CTE
WHERE RN = 1;
As an aside, please try to use tabla aliases instead of the whole table name in your queries.
*Disclaimer: You said that you wanted the max date, but the selected values in your post were those with the min date, so I used that criteria in my answer
This method just limits your history table to those with the MINdate as you described.
SELECT
REQCOMMIT.COMMITSTATUS,
NOTEHISTORY.NOTE,
NOTEHISTORY.MODIFIEDDATETIME,
NOTEHISTORY.COMMITRECID
FROM REQCOMMIT
INNER JOIN NOTEHISTORY ON REQCOMMIT.RECID = NOTEHISTORY.COMMITRECID
INNER JOIN (SELECT COMMITRECID, MIN(MODIFIEDDATETIME) DT FROM NOTEHISTORY GROUP BY COMMITRECID) a on a.COMMITRECID = NOTEHISTORY.COMMITRECID and a.DT = NOTEHISTORY.MODIFIEDDATETIME
WHERE REQCOMMIT.PORECID = 1234

Group by not working to get count of a column with other max record in sql

I have a table named PublishedData, see image below
I'm trying to get the output like, below image
I think you can use a query like this:
SELECT dt.DistrictName, ISNULL(dt.Content, 'N/A') Content, dt.UpdatedDate, mt.LastPublished, mt.Unpublished
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY DistrictName ORDER BY UpdatedDate DESC, ISNULL(Content, 'zzzzz')) seq
FROM PublishedData) dt
INNER JOIN (
SELECT DistrictName, MAX(LastPublished) LastPublished, COUNT(CASE WHEN IsPublished = 0 THEN 1 END) Unpublished
FROM PublishedData
GROUP BY DistrictName) mt
ON dt.DistrictName = mt.DistrictName
WHERE
dt.seq = 1;
Because I think you use an order over UpdatedDate, Content to gain you two first columns.
Check out something like this (I don't have your tables, but you will get the idea where to follow with your query):
SELECT DirectName,
MAX(UpdatedDate),
MAX(LastPublished),
(
SELECT COUNT(*)
FROM PublishedData inr
WHERE inr.DirectName = outr.DirectName
AND inr.IsPublished = 0
) AS Unpublished
FROM PublishedData outr
GROUP BY DirectName
We should required a unique identity for that required output in PublishedData Table,Because We can't get the Latest content from given Schema.
If you want data apart from content like DistictName,updatedDate,LastPublishedDate and count of Unpublished records ,Please use Query given below :
select T1.DistrictName,T1.UpdatedDate,T1.LastPublished,T2.Unpublished from
(select DistrictName,Max(UpdateDate) as UpdatedDate,Max(LastPublished) as LastPublished from PublishedData group by DistrictName) T1
inner join
(select DistrictName,count(IsPublished) as Unpublished from PublishedData where isPublished=0 group by DistrictName) T2 ON T1.DistrictName=T2.DistrictName ORDER BY T2.Unpublished DESC

Seemingly Simple Query in Pl Sql

I have a table "defects" in the following format:
id status stat_date line div area
1 Open 09/21/09 F A cube
1 closed 01/01/10 F A cube
2 Open 10/23/09 B C Back
3 Open 11/08/09 S B Front
3 closed 12/12/09 S B Front
My problem is that I want to write a query that just extracts the "Open" defects. If I write a query to simply extract all open defects, then I get the wrong result because there are some defects,
that have 2 records associated with it. For example, with the query that I wrote I would get defect id#s 1 and 3 in my result even though they are closed. I hope I have explained my problem well. Thank you.
Use:
SELECT t.*
FROM DEFECTS t
JOIN (SELECT d.id,
MAX(d.stat_date) 'msd'
FROM DEFECTS d
GROUP BY d.id) x ON x.id = t.id
AND x.msd = t.stat_date
WHERE t.status != 'closed'
The join is getting the most recent date for each id value.
Join back to the original table on based on the id and date in order to get only the most recent rows.
Filter out those rows with the closed status to know the ones that are currently open
So you want to get the most recent row per id and of those, only select those that are open. This is a variation of the common greatest-n-per-group problem.
I would do it this way:
SELECT d1.*
FROM defects d1
LEFT OUTER JOIN defects d2
ON (d1.id = d2.id AND d1.stat_date < d2.stat_date)
WHERE d2.id IS NULL
AND d1.status = 'Open';
Select *
from defects d
where status = 'Open'
and not exists (
select 1 from defects d1
where d1.status = 'closed'
and d1.id = d.id
and d1.stat_date > d.stat_date
)
This should get what you want. I wouldn't have a record for open and closing a defect, rather just a single record to track a single defect. But that may not be something you can change easily.
SELECT id FROM defects
WHERE status = 'OPEN' AND id NOT IN
(SELECT id FROM defects WHERE status = 'closed')
This query handles multiple opens/closes/opens, and only does one pass through the data (i.e. no self-joins):
SELECT * FROM
(SELECT DISTINCT
id
,FIRST_VALUE(status)
OVER (PARTITION BY id
ORDER BY stat_date desc)
as last_status
,FIRST_VALUE(stat_date)
over (PARTITION BY id
ORDER BY stat_date desc)
AS last_stat_date
,line
,div
,area
FROM defects)
WHERE last_status = 'Open';